static int write_to_swap(page_meta * swapped_meta) { struct aiocb * aio_init_table[1]; struct aiocb aio_init; aio_init_table[0] = &aio_init; aiocb_setup(&aio_init, swapped_meta->page_index, swapped_meta->frame_number); if (increase_io_operations_counter() == ERROR) return ERROR; if (swapped_meta->modified) { callback_wrapper(2, swapped_meta->page_index, swapped_meta->frame_number); if (aio_write(&aio_init) == ERROR) return ERROR; if (aio_suspend((const struct aiocb * const *)aio_init_table, 1, NULL) == ERROR) return ERROR; callback_wrapper(3, swapped_meta->page_index, swapped_meta->frame_number); } swapped_meta->frame_number = -1; if (pthread_mutex_unlock(&swapped_meta->lock) != SUCCESS) return ERROR; return SUCCESS; }
static int lio_wait(struct lio_state *st) { int i, err, got_err = 0; int cnt = st->cnt; struct aiocb **cbs = st->cbs; for (;;) { for (i=0; i<cnt; i++) { if (!cbs[i]) continue; err = aio_error(cbs[i]); if (err==EINPROGRESS) break; if (err) got_err=1; cbs[i] = 0; } if (i==cnt) { if (got_err) { errno = EIO; return -1; } return 0; } if (aio_suspend((void *)cbs, cnt, 0)) return -1; } }
static void handle_aio_events(struct fs_mount *mount) { int fd, ret, count, i, notify; evtchn_port_t port; /* AIO control block for the evtchn file destriptor */ struct aiocb evtchn_cb; const struct aiocb * cb_list[mount->nr_entries]; int request_ids[mount->nr_entries]; /* Prepare the AIO control block for evtchn */ fd = xc_evtchn_fd(mount->evth); bzero(&evtchn_cb, sizeof(struct aiocb)); evtchn_cb.aio_fildes = fd; evtchn_cb.aio_nbytes = sizeof(port); evtchn_cb.aio_buf = &port; assert(aio_read(&evtchn_cb) == 0); wait_again: /* Create list of active AIO requests */ count = 0; for(i=0; i<mount->nr_entries; i++) if(mount->requests[i].active) { cb_list[count] = &mount->requests[i].aiocb; request_ids[count] = i; count++; } /* Add the event channel at the end of the list. Event channel needs to be * handled last as it exits this function. */ cb_list[count] = &evtchn_cb; request_ids[count] = -1; count++; /* Block till an AIO requset finishes, or we get an event */ while(1) { int ret = aio_suspend(cb_list, count, NULL); if (!ret) break; assert(errno == EINTR); } for(i=0; i<count; i++) if(aio_error(cb_list[i]) != EINPROGRESS) { if(request_ids[i] >= 0) dispatch_response(mount, request_ids[i]); else goto read_event_channel; } RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&mount->ring, notify); printf("Pushed responces and notify=%d\n", notify); if(notify) xc_evtchn_notify(mount->evth, mount->local_evtchn); goto wait_again; read_event_channel: assert(aio_return(&evtchn_cb) == sizeof(evtchn_port_t)); assert(xc_evtchn_unmask(mount->evth, mount->local_evtchn) >= 0); }
static int init_pages() { for (int i = 0; i < globals.addr_space_size; ++i) { if (pthread_mutex_init(&globals.metadata[i].lock, NULL) == ERROR) return ERROR; globals.metadata[i].page_index = i; globals.metadata[i].reference_counter = 0; globals.metadata[i].frame_number = -1; globals.metadata[i].modified = false; } for (int i = 0; i < globals.mem_size; ++i) { globals.pages[i].data = calloc(globals.page_size, sizeof(uint8_t)); if (globals.pages[i].data == NULL) return ERROR; globals.metadata[i].frame_number = i; globals.pages[i].meta = &globals.metadata[i]; } struct aiocb * aio_init_table[1]; struct aiocb aio_init; aio_init_table[0] = &aio_init; aiocb_setup(&aio_init, 0, 0); for (int i = 0; i < globals.addr_space_size; ++i) { if (aio_write(&aio_init) == ERROR) return ERROR; if (aio_suspend((const struct aiocb * const *)aio_init_table, 1, NULL) == ERROR) return ERROR; } return SUCCESS; }
static buffer_t *wait_for_free_buffer(void) { int i; const struct aiocb * p[NB_BUFFERS]; buffer_t *freeBuffer = NULL; for (i = 0; i < NB_BUFFERS; i++) { p[i] = &buffersList[i].acb; } do { int error = aio_suspend(p, NB_BUFFERS, NULL); if (0 == error) { /* look for the ended aio write */ for (i = 0; i < NB_BUFFERS; i++) { if (BUFFER_WRITTING == buffersList[i].state) { error = aio_error(&buffersList[i].acb); if (error != EINPROGRESS) { error = aio_return(&buffersList[i].acb); if (error < 0) { ERROR_MSG("aio write ended with error %d (%s)", error, strerror(error)); } buffersList[i].state = BUFFER_FREE; freeBuffer = &buffersList[i]; } } /* (BUFFER_WRITTING == buflist[i].state) */ } /* for(i=0;i<NBUFFERS;i++) */ } else if (-1 == error) { INFO_MSG("aio_suspend interrupted by a signal"); } else { ERROR_MSG("aio_suspend error %d (%s)", error, strerror(error)); } } while (NULL == freeBuffer); return freeBuffer; }
void write(iterator sa, iterator se) { lock.lock(); if ( high-low == numbuffers ) { aiocb *waitlist[1] = { &contexts[low%numbuffers] }; // std::cerr << "waiting for " << low << std::endl; aio_suspend (waitlist,1,0); low++; } u_int64_t const len = se-sa; // std::cerr << "writing " << s.size() << std::endl; buffers[high % numbuffers] = AutoArray<char>(len); std::copy ( sa, se, buffers[high%numbuffers].get() ); memset ( &contexts[high%numbuffers], 0, sizeof(aiocb) ); contexts[high%numbuffers].aio_fildes = fd; contexts[high%numbuffers].aio_buf = buffers[high % numbuffers].get(); contexts[high%numbuffers].aio_nbytes = len; contexts[high%numbuffers].aio_offset = 0; contexts[high%numbuffers].aio_sigevent.sigev_notify = SIGEV_NONE; aio_write( & contexts[high%numbuffers] ); high++; lock.unlock(); }
static int do_wait (struct aiocb **cbp, size_t nent, int allowed_err) { int go_on; size_t cnt; int result = 0; do { aio_suspend ((const struct aiocb *const *) cbp, nent, NULL); go_on = 0; for (cnt = 0; cnt < nent; ++cnt) if (cbp[cnt] != NULL) { if (aio_error (cbp[cnt]) == EINPROGRESS) go_on = 1; else { if (aio_return (cbp[cnt]) == -1 && (allowed_err == 0 || aio_error (cbp[cnt]) != allowed_err)) { error (0, aio_error (cbp[cnt]), "Operation failed\n"); result = 1; } cbp[cnt] = NULL; } } } while (go_on); return result; }
void write(iterator sa, iterator se) { lock.lock(); // wait for free context if all buffers are in use if ( high-low == numbuffers ) { aiocb *waitlist[1] = { &contexts[low%numbuffers] }; aio_suspend (waitlist,1,0); low++; } uint64_t const len = se-sa; buffers[high % numbuffers] = ::libmaus::autoarray::AutoArray<char>(len); std::copy ( sa, se, buffers[high%numbuffers].get() ); memset ( &contexts[high%numbuffers], 0, sizeof(aiocb) ); contexts[high%numbuffers].aio_fildes = fd; contexts[high%numbuffers].aio_buf = buffers[high % numbuffers].get(); contexts[high%numbuffers].aio_nbytes = len; contexts[high%numbuffers].aio_offset = 0; contexts[high%numbuffers].aio_sigevent.sigev_notify = SIGEV_NONE; aio_write( & contexts[high%numbuffers] ); high++; lock.unlock(); }
Status WaitUntilComplete(aiocb& cb, size_t queueDepth) { #if CONFIG2_FILE_ENABLE_AIO if(queueDepth > 1) { aiocb* const cbs = &cb; timespec* const timeout = 0; // infinite SUSPEND_AGAIN: errno = 0; const int ret = aio_suspend(&cbs, 1, timeout); if(ret != 0) { if(errno == EINTR) // interrupted by signal goto SUSPEND_AGAIN; WARN_RETURN(StatusFromErrno()); } const int err = aio_error(&cb); ENSURE(err != EINPROGRESS); // else aio_return is undefined ssize_t bytesTransferred = aio_return(&cb); if(bytesTransferred == -1) // transfer failed { errno = err; WARN_RETURN(StatusFromErrno()); } cb.aio_nbytes = (size_t)bytesTransferred; } #else UNUSED2(cb); UNUSED2(queueDepth); #endif return INFO::OK; }
int eDVBRecordFileThread::AsyncIO::wait() { if (aio.aio_buf != NULL) // Only if we had a request outstanding { while (aio_error(&aio) == EINPROGRESS) { eDebug("[eDVBRecordFileThread] Waiting for I/O to complete"); struct aiocb* paio = &aio; int r = aio_suspend(&paio, 1, NULL); if (r < 0) { eDebug("[eDVBRecordFileThread] aio_suspend failed: %m"); return -1; } } int r = aio_return(&aio); aio.aio_buf = NULL; if (r < 0) { eDebug("[eDVBRecordFileThread] wait: aio_return returned failure: %m"); return -1; } } return 0; }
int test_aio() { int ret; struct aiocb cb, *pcb = &cb; char buf[100] = ""; cb.aio_fildes = STDIN_FILENO; cb.aio_offset = 0; cb.aio_buf = buf; cb.aio_nbytes = 10; cb.aio_reqprio = 0; cb.aio_sigevent.sigev_notify = SIGEV_NONE; ret = aio_read(&cb); if (ret < 0) err_sys("aio_read"); for (;;) { ret = aio_suspend(&pcb, 1, NULL); if (ret != 0) { if (ret == -1) { if (errno != EINTR) err_sys("aio_error"); else continue; } } ret = aio_return(&cb); printf("read %d bytes, buf: %s\n", ret, buf); break; } return 0; }
// gcc 5_async.c -o async -lrt 비동기 io를 하려면 rt라이브러리와 링크해야 함 int main() { int fd = open("file.txt", O_RDONLY); // 비동기 io를 위한 작업들 struct aiocb myaiocb; // = {0}; // async io control block memset (&myaiocb, 0, sizeof(myaiocb)); myaiocb.aio_buf = malloc(sizeof(char)*10); // 읽어올 버퍼(힙에 할당해야 한다) myaiocb.aio_fildes = fd; // 파일 번호 myaiocb.aio_nbytes = 10; // 버퍼 크기 myaiocb.aio_offset = 0; // 파일 offset int ret = aio_read(&myaiocb); // 비동기 읽기 요청 printf("비동기 읽기 시작 : %d\n", ret); // 비동기 작업이 종료되는것을 대기한다. struct aiocb* aio_list[1]; memset( aio_list, 0, sizeof(aio_list)); aio_list[0] = &myaiocb; ret = aio_suspend( aio_list, 1, 0); printf("ret : %d \n" , ret); // 비동기 작업의 결과를 얻어온다. ret = aio_return(&myaiocb); printf("ret : %d\n", ret); printf("buff: %s \n", myaiocb.aio_buf); }
ssize_t read(client_ctx_ptr ctx, const std::string &filename, void *buf, size_t nbytes, off_t offset) { ssize_t r; giocb aio; aio.aio_buf = buf; aio.aio_nbytes = nbytes; aio.aio_offset = offset; if (ctx == nullptr) { errno = EINVAL; return (r = -1); } if ((r = aio_read(ctx, filename, &aio)) < 0) { return r; } r = aio_suspend(ctx, &aio, nullptr); if (r == 0) { r = aio_return(ctx, &aio); } aio_finish(ctx, &aio); return r; }
int main(){ int fd, ret; struct aiocb my_aiocb; fd = open( "file.txt", O_RDONLY ); if (fd < 0) perror("open"); struct sigaction sig_act; sigemptyset(&sig_act.sa_mask); sig_act.sa_flags = SA_SIGINFO; sig_act.sa_sigaction = aio_completion_handler; /* Zero out the aiocb structure (recommended) */ bzero( (char *)&my_aiocb, sizeof(struct aiocb) ); /* Allocate a data buffer for the aiocb request */ my_aiocb.aio_buf = malloc(BUFSIZE+1); if (!my_aiocb.aio_buf) perror("malloc"); /* Initialize the necessary fields in the aiocb */ my_aiocb.aio_fildes = fd; my_aiocb.aio_nbytes = BUFSIZE; my_aiocb.aio_offset = 0; my_aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL; my_aiocb.aio_sigevent.sigev_signo = SIGIO; my_aiocb.aio_sigevent.sigev_value.sival_ptr = &my_aiocb; ret = sigaction( SIGIO, &sig_act, NULL ); if( ret ){ perror("sigaction"); } aio_read( &my_aiocb ); // if( ret == 0 ){ // printf("EOF\n"); // printf("Total read %zd bytes\n", total); // } // else{ // perror("aio_read2"); // } const struct aiocb *const cblist[1] = { &my_aiocb }; while(1){ aio_suspend( cblist, 1, NULL ); if( done ){ break; } } return 0; }
static int suspend(const struct aiocb * const list[], int n, struct timespec *timeout) { if (timeout) { int t = novacom_usbll_get_timeout(usbll_handle); timeout->tv_sec = t / 1000; timeout->tv_nsec = (t % 1000) * 1000000; } return aio_suspend(list, n, timeout); }
void waitForNextBuffer() { aiocb *waitlist[1] = { &contexts[low%numbuffers] }; int r = aio_suspend (waitlist,1,0); if ( r != 0 ) { std::cerr << "ERROR: " << strerror(errno) << std::endl; } }
static void AIOwait(raf_t raf){ if(raf->pending==0) return; const struct aiocb* list[1]; list[0]=&(raf->request); // TODO check out why aio_suspend complains about 1st argument. if (aio_suspend((void*)list,1,NULL)){ FatalCall(1,error,"aio_suspend for %s",raf->shared.name); } if (aio_error(list[0])){ FatalCall(1,error,"aio_error for %s",raf->shared.name); } raf->pending=0; }
void aio_check_functions(struct aiocb *ai) { (void)aio_cancel(0, ai); (void)aio_error(ai); #if _POSIX_FSYNC > 0 || _POSIX_SYNCHRONIZED_IO > 0 (void)aio_fsync(0, ai); #endif (void)aio_read(ai); (void)aio_return(ai); (void)aio_suspend((const struct aiocb * const *)1234, 0, (struct timespec *)0); (void)aio_write(ai); (void)lio_listio(0, (struct aiocb * const *)1234, 0, (struct sigevent *)0); }
void HostProxy_GadgetFS::receive_data(__u8 endpoint,__u8 attributes,__u16 maxPacketSize,__u8** dataptr, int* length, int timeout) { if (!endpoint) { fprintf(stderr,"trying to receive %d bytes on EP00\n",*length); return; } if (endpoint & 0x80) { fprintf(stderr,"trying to receive %d bytes on an in EP%02x\n",*length,endpoint); return; } int number=endpoint&0x0f; if (!p_epout_async[number]) { fprintf(stderr,"trying to receive %d bytes on a non-open EP%02x\n",*length,endpoint); return; } aiocb* aio=p_epout_async[number]; int rc=aio_error(aio); if (rc==EINPROGRESS && timeout) { struct timespec ts; ts.tv_sec = timeout/1000; ts.tv_nsec = 1000000L * (timeout%1000); if (aio_suspend(&aio,1,&ts)) { return; } else { rc=aio_error(aio); } } if (rc) { if (rc==EINPROGRESS) {return;} fprintf(stderr,"Error during async aio on EP %02x %d %s (%s)\n",endpoint,rc,strerror(rc), __func__); } else { rc=aio_return(aio); if (rc == -1) { std::cerr << "Bad aio_return (rc " << errno << ", '" << std::strerror(errno) << "')\n"; return; } if (debugLevel > 2) std::cerr << "Received " << rc << " bytes from gadgetfs EP" << std::hex << (unsigned)endpoint << std::dec << '\n'; *dataptr=(__u8*)malloc(rc); memcpy(*dataptr,(void*)(aio->aio_buf),rc); *length=rc; rc=aio_read(aio); if (rc) { delete(aio);fprintf(stderr,"Error submitting aio for EP%02x %d %s\n",endpoint,errno,strerror(errno)); p_epout_async[number]=NULL; } } }
bool HostProxy_GadgetFS::send_wait_complete(__u8 endpoint,int timeout) { if (!endpoint) return true; if (!(endpoint & 0x80)) { fprintf(stderr,"trying to check send on an out EP%02x\n",endpoint); return false; } int number=endpoint&0x0f; if (!p_epin_async[number]) { fprintf(stderr,"trying to check send on a non-open EP%02x\n",endpoint); return false; } if (!p_epin_active[number]) return true; aiocb* aio=p_epin_async[number]; int rc=aio_error(aio); if (rc==EINPROGRESS && timeout) { struct timespec ts; ts.tv_sec = timeout/1000; ts.tv_nsec = 1000000L * (timeout%1000); if (aio_suspend(&aio,1,&ts)) { rc=0; } else { rc=aio_error(aio); } } if (rc==EINPROGRESS) return false; free((void*)(aio->aio_buf)); aio->aio_buf=NULL; aio->aio_nbytes=0; if (rc) { fprintf(stderr,"Error during async aio on EP %02x %d %s (%s)\n",endpoint,rc,strerror(rc), __func__); p_epin_active[number]=false; return true; } else { rc=aio_return(aio); if (!rc) return true; if (rc == -1) { std::cerr << "Bad aio_return (rc " << errno << ", '" << std::strerror(errno) << "')\n"; return false; } if (debugLevel > 2) std::cerr << "Sent " << rc << " bytes to gadgetfs EP" << std::hex << (unsigned)endpoint << std::dec << '\n'; p_epin_active[number]=false; return true; } }
static int do_write_aio_posix(int fd, uint64_t offset, char *buf, int len, struct task *task) { struct timespec ts; struct aiocb cb; struct aiocb const *p_cb; int rv; memset(&ts, 0, sizeof(struct timespec)); ts.tv_sec = task->io_timeout_seconds; memset(&cb, 0, sizeof(struct aiocb)); p_cb = &cb; cb.aio_fildes = fd; cb.aio_buf = buf; cb.aio_nbytes = len; cb.aio_offset = offset; rv = aio_write(&cb); if (rv < 0) return -1; rv = aio_suspend(&p_cb, 1, &ts); if (!rv) return 0; /* the write timed out, try to cancel it... */ rv = aio_cancel(fd, &cb); if (rv < 0) return -1; if (rv == AIO_ALLDONE) return 0; if (rv == AIO_CANCELED) return -EIO; /* Functions that depend on the timeout might consider * the action failed even if it will complete if that * happened after the alloted time frame */ if (rv == AIO_NOTCANCELED) return -EIO; /* undefined error condition */ return -1; }
int main(){ int fd, ret; struct aiocb my_aiocb; fd = open( "file.txt", O_RDONLY ); if (fd < 0) perror("open"); /* Zero out the aiocb structure (recommended) */ bzero( (char *)&my_aiocb, sizeof(struct aiocb) ); /* Allocate a data buffer for the aiocb request */ my_aiocb.aio_buf = malloc(BUFSIZE+1); if (!my_aiocb.aio_buf) perror("malloc"); /* Initialize the necessary fields in the aiocb */ my_aiocb.aio_fildes = fd; my_aiocb.aio_nbytes = BUFSIZE; my_aiocb.aio_offset = 0; size_t total = 0; do { ret = aio_read( &my_aiocb ); if (ret < 0) perror("aio_read"); // while ( aio_error( &my_aiocb ) == EINPROGRESS ){ // printf("Working...\n"); // } const struct aiocb *const cblist[1] = { &my_aiocb }; aio_suspend( cblist, 1, NULL ); if ((ret = aio_return( &my_aiocb )) > 0) { //printf("Read %d bytes\n", ret); total += ret; my_aiocb.aio_offset += ret; } } while( ret > 0); if( ret == 0 ){ printf("EOF\n"); printf("Total read %zd bytes\n", total); } else{ perror("aio_read2"); } return 0; }
static ssize_t aio_read_wrapper(int d, void *buf, size_t nbytes) { struct aiocb aiocb, *aiocb_array[1]; bzero(&aiocb, sizeof(aiocb)); aiocb.aio_fildes = d; aiocb.aio_buf = buf; aiocb.aio_nbytes = nbytes; if (aio_read(&aiocb) < 0) return (-1); aiocb_array[0] = &aiocb; if (aio_suspend(aiocb_array, 1, NULL) < 0) return (-1); return (aio_return(&aiocb)); }
void signal_handler(int signo){ int ret; ret=aio_read(&my_aiocb); if(ret <0) perror("aio_read"); ret=aio_suspend(cblist, MAX_LIST, NULL); if(ret <0) perror("aio_suspend"); if((ret=aio_return(&my_aiocb)) >0) { printf("value:%s\n", (char*)my_aiocb.aio_buf); memset((char*)my_aiocb.aio_buf, 0, BUF_SIZE); } }
int main() { int s; static struct aiocb readrq; static const struct aiocb *readrqv[2]={&readrq, NULL}; char buf[4096]; char buf2[4096]; size_t size; struct sockaddr_in addr; struct hostent *srv; s=socket(PF_INET, SOCK_STREAM, 0); srv=gethostbyname("www.nsu.ru"); addr.sin_family=AF_INET; addr.sin_port=htons(80); if (srv) { addr.sin_addr.s_addr=*((unsigned long*)srv->h_addr); } else { inet_aton("193.124.215.195", &addr.sin_addr); } if (connect(s, (struct sockaddr*)&addr, sizeof addr)) { perror("connecting to server"); exit(1); } memset(&readrq, 0, sizeof readrq); readrq.aio_fildes=s; readrq.aio_buf=buf; readrq.aio_nbytes=sizeof buf; if (aio_read(&readrq)) { perror("aio_read"); exit(1); } write(s, req, (sizeof req)-1); while(1) { aio_suspend(readrqv, 1, NULL); size=aio_return(&readrq); if (size>0) { write(1, buf, size); aio_read(&readrq); } else if (size==0) { break; } else { perror("reading from socket"); } } }
/** * wait until all write requests have finished **/ void flush() { while ( high-low ) { aiocb *waitlist[1] = { &contexts[low%numbuffers] }; aio_suspend (waitlist,1,0); ssize_t ret = aio_return ( &contexts[low%numbuffers] ); assert ( ret == static_cast<ssize_t>(contexts[low%numbuffers].aio_nbytes) ) ; // std::cerr << "WRITTEN: " << ret << " requested " << contexts[low%numbuffers].aio_nbytes << std::endl; low++; } if ( fd != STDOUT_FILENO ) if ( fsync(fd) ) std::cerr << "Failure in fsync: " << strerror(errno) << std::endl; }
int write_page(page *page) /* Function writes page into the [data.file] using the aio. * * * * RETURN VALUE: * * 0 success * * PSIM_EIO aio operation failed */ { struct aiocb request; struct aiocb *tab[1]; init_aiocb(&request, page); tab[0] = &request; CHECK_MONE(aio_write(&request), PSIM_EIO); CHECK_MONE(aio_suspend((const struct aiocb *const *)tab, 1, NULL), PSIM_EIO); CHECK_NZERO(aio_error(&request), PSIM_EIO); return 0; }
static int read_from_swap(page * current_page, unsigned page_num, unsigned frame_num) { struct aiocb * aio_init_table[1]; struct aiocb aio_init; aio_init_table[0] = &aio_init; aiocb_setup(&aio_init, page_num, frame_num); callback_wrapper(4, page_num, frame_num); aio_read(&aio_init); aio_suspend((const struct aiocb * const *)aio_init_table, 1, NULL); callback_wrapper(5, page_num, frame_num); if (decrease_io_operations_counter() == ERROR) return ERROR; return SUCCESS; }
static void flush_data(void) { const struct aiocb * p[1]; /* Set up AIOCB */ currentBuffer->acb.aio_fildes = currentFile->fd; __sync_fetch_and_add(¤tFile->nb_running_aiocb,1); /* GCC's atomic add */ currentBuffer->acb.aio_offset = seek_ptr; seek_ptr += currentBuffer->used_size; currentBuffer->acb.aio_buf = currentBuffer->buffer; currentBuffer->acb.aio_nbytes = currentBuffer->used_size; currentBuffer->acb.aio_reqprio = 0; currentBuffer->acb.aio_sigevent.sigev_notify = SIGEV_NONE; currentBuffer->acb.aio_sigevent.sigev_signo = 0; currentBuffer->acb.aio_sigevent.sigev_value.sival_ptr = NULL; /* Mark buffer as being written out */ currentBuffer->state = BUFFER_WRITTING; DEBUG_MSG("flushing remaining data..."); /* Fire off the asynchronous I/O */ if (aio_write(¤tBuffer->acb) < 0) { const int error = aio_error(¤tBuffer->acb); ERROR_MSG("flush aio_write error %d (%s)", error, strerror(error)); } p[0] = ¤tBuffer->acb; do { int error = aio_suspend(p, 1, NULL); if (0 == error) { error = aio_error(p[0]); if (error != EINPROGRESS) { if ((error = aio_return(p[0])) != BUFFER_SIZE) { ERROR_MSG("aio write ended with error %d (%s)", error, strerror(error)); } currentBuffer->state = BUFFER_FREE; } } else if (error != -1) { ERROR_MSG("flush_data aio_suspend error %d (%s)", error, strerror(error)); } } while (BUFFER_WRITTING == currentBuffer->state); /* * this is the last buffer: close the file */ aio_closelog(); }
void fileio_aio_write() { int fd; fd = open("test", O_RDWR); if(fd == -1) errexit("open"); // 비동기 I/O Request(aio)를 기술하는 구조체 struct aiocb my_aiocb; bzero((void *)&my_aiocb, sizeof(struct aiocb)); //0으로 초기화하는 방법 char buf[BUF_SIZE]; strcpy(buf, "This is asynchronous call test!\n"); my_aiocb.aio_fildes = fd; // 파일 디스크립터 my_aiocb.aio_nbytes = strlen(buf); // 버퍼 크기 my_aiocb.aio_offset = 0; // 파일 옵셋 // aio 완료 통지는 스레드 방식으로 설정한다. my_aiocb.aio_sigevent.sigev_notify = SIGEV_THREAD; my_aiocb.aio_sigevent.sigev_notify_function = thread_func; my_aiocb.aio_sigevent.sigev_notify_attributes = NULL; // 스레드 속성 my_aiocb.aio_sigevent.sigev_value.sival_ptr = &my_aiocb; // 스레드 생성시 전달할 파라미터. sigval_t sv의 sv.sival_ptr로 받을 수 있다. // 지정한 복수의 aio가 완료될 때까지 대기하는 aio_suspend 함수 호출시, 복수의 aio를 지정하는 aio 배열 const struct aiocb *list_aiocb[MAX_LIST]; bzero((void *)list_aiocb, sizeof(list_aiocb)); list_aiocb[0] = &my_aiocb; // 쓰기 aio 수행. 성공하면 0을 리턴한다. if(aio_write(&my_aiocb) == -1) errexit("aio_write"); // 리스트로 지정한 aio가 완료되거나 timeout이 발생할 때까지(여기서 무한) 스레드를 대기시킨다. // aio가 완료되면 0을 리턴한다. if(aio_suspend(list_aiocb, MAX_LIST, NULL) == -1) errexit("aio_suspend"); /* 또는 aio_suspend를 호출하지 않고 다른 작업을 수행할 수 있다. aio가 완료되면 스레드가 호출된다. */ // sleep(5); }