linux system software 에서 trace replay를 통한 성능 측정에 필요했던 data structure를 정리하도록 하겠다.
struct thread_info_t {
int tid;
pthread_mutex_t mutex;
pthread_cond_t cond_main, cond_sub;
io_context_t io_ctx;
struct io_event events[MAX_QDEPTH];
int queue_depth;
int queue_count;
int active_count;
int fd;
int fsync_period;
struct io_job *th_jobs[MAX_QDEPTH];
void *th_buf[MAX_QDEPTH];
int buf_cur;
struct io_stat_t io_stat;
struct trace_info_t *trace;
int done;
};
struct io_job {
struct iocb iocb;
struct flist_head list;
struct timeval start_time, stop_time;
long long offset; // in bytes
size_t bytes;
int rw; // is read
char *buf;
};
'io_ctx'는 'io_context_t' type 변수로, 비동기 I/O (Asynchronous I/O) 작업을 관리하는 context를 나타낸다. 이 context는 kernel과 user space 사이에서 비동기 I/O 요청을 효율적으로 처리하기 위해 사용된다. Linux에서 비동기 I/O는 'io_submit', 'io_getevents'와 같은 system call을 통해 비동기 I/O 작업을 수행할 수 있게 해준다.
#include <libaio.h>
/* context 초기화
'io_setup' system call을 통해 비동기 I/O context를 초기화한다. 'MAX_EVENTS'는 context에서 동시에 처리할 수 있는 최대 I/O events 수를 지정한다.
*/
io_context_t io_ctx;
memset(&io_ctx, 0, sizeof(io_ctx));
int ret = io_setup(MAX_EVENTS, &io_ctx);
if(ret < 0) {
perror("io_setup");
return -1;
}
/* I/O 작업 submit
'io_prep_pread' 함수를 사용해서 읽기 작업을 준비하고, 'io_submit'을 통해 I/O 요청을 제출한다.
*/
struct iocb cb;
struct iocb *cbs[1];
io_prep_pread(&cb, fd, buffer, buffer_size, offset);
cbs[0] = &cb;
ret = io_submit(io_ctx, 1, cbs);
if (ret < 0) {
perror("io_submit");
return -1;
}
/* 완료된 I/O 이벤트 수집
'io_getevents'를 사용해서 완료된 I/O 이벤트를 수집한다. 'min_nr'와 'max_nr'는 수집할 최소 및 최대 이벤트 수를 지정한다.
*/
struct io_event events[MAX_EVENTS];
ret = io_getevents(io_ctx, min_nr, max_nr, events, NULL);
if (ret < 0) {
perror("io_getevents");
return -1;
}
for (int i=0; i < ret; i++) {
// event 처리 코드
}
/* context 해제
모든 작업이 완료되면 'io_destroy'를 사용해서 비동기 I/O context를 해제한다.
*/
ret = io_destroy(io_ctx);
if (ret < 0) {
perror("io_destroy");
return -1;
}
요약하자면 'io_ctx'는 비동기 I/O 작업을 관리하는 context로, I/O 요청의 제출 및 완료 이벤트의 수집을 효율적으로 처리하기 위해 사용된다. 이를 통해 블로킹 없이 비동기적으로 I/O 작업을 수행할 수 있으며, 시스템의 동시성과 성능을 향상시킬 수 있다.