2016-12-08 17 views
0

我试图用aio_read(3)aio_write(3)以异步方式模仿sendfile(2)的功能。大文件上的aio_write

似乎一切正常,除了测试大(> 150k)文件。

我有一个简单struct io_request我使用的跟踪转移:

struct io_request { 
    int status; 
    struct aiocb *aiocbp; 
    int sfd; 
}; 

首先,我建立了aio_read()电话:

struct io_request * ioreq = malloc(sizeof(struct io_request)); 
ioreq->status = EINPROGRESS; 
ioreq->sfd = sfd; 

struct aiocb * aiocbreq = malloc(sizeof(struct aiocb)); 
memset(aiocbreq, 0, sizeof(struct aiocb)); 

ioreq->aiocbp = aiocbreq; 

ioreq->aiocbp->aio_fildes = ffd; 

if (ioreq->aiocbp->aio_fildes == -1) { 
    perror("aio_fildes"); 
} 

ioreq->aiocbp->aio_buf = malloc(st.st_size); 
if (ioreq->aiocbp->aio_buf == NULL) { 
    perror("aio_buf malloc"); 
} 

ioreq->aiocbp->aio_nbytes = st.st_size; 
ioreq->aiocbp->aio_reqprio = 0; 
ioreq->aiocbp->aio_offset = 0; 
ioreq->aiocbp->aio_sigevent.sigev_signo = IO_READ_SIGNAL; 
ioreq->aiocbp->aio_sigevent.sigev_value.sival_ptr = ioreq; 
if (aio_read(ioreq->aiocbp) == -1) { 
    perror("aio_read"); 
} 

然后后来是在IO_READ_SIGNAL处理程序捕获:

static void 
aio_read_handler(int sig, siginfo_t *si, void *ucontext) 
{ 
    if (si->si_code == SI_ASYNCIO) { 
     struct io_request *ioreq = si->si_value.sival_ptr; 

     // Build the AIO write request 
     struct aiocb aiocbreq; 
     memset(&aiocbreq, 0, sizeof(struct aiocb)); 
     aiocbreq.aio_fildes = ioreq->sfd; 
     aiocbreq.aio_buf = ioreq->aiocbp->aio_buf; 
     aiocbreq.aio_nbytes = ioreq->aiocbp->aio_nbytes; 
     aiocbreq.aio_sigevent.sigev_signo = IO_WRITE_SIGNAL; 
     aiocbreq.aio_sigevent.sigev_value.sival_ptr = ioreq; 

     if (aio_write((void *) &aiocbreq) == -1) { 
      perror("aio_write"); 
     } 
    } 
} 

I ca n确认处理程序内部,即使对于大文件,ioreq->aiocbp->aio_buf的内容也是完整且完整的。

后来,aio_write()被捕获在IO_WRITE_SIGNAL处理程序:

static void 
aio_write_handler(int sig, siginfo_t *si, void *ucontext) 
{ 
    if (si->si_code == SI_ASYNCIO) { 
     struct io_request *ioreq = si->si_value.sival_ptr; 

     ssize_t bytes_written = aio_return(ioreq->aiocbp); 
     printf("Wrote %zu of %zu bytes\n", bytes_written, ioreq->aiocbp->aio_nbytes); 
     //free(ioreq->aiocbp); 
     //free(ioreq); 

     if (aio_error(ioreq->aiocbp) != 0) { 
      perror("aio_write_handler"); 
     } 
    } 
} 

此时aio_write()应该已经完成​​。我检查返回值并据此采取行动。这两个调用都会报告已写入的相应字节数,并且在写入期间不会出现错误。

更大的应用程序是HTTP服务器。我推测这个问题是有道理的,因为远程客户端无法快速读取以跟上aio_write()。当我执行sendfile()时,我不得不多次拨打sendfile()来完成文件传输。

几个直接的问题:

  • 为什么aio_return()aio_error()没有报告任何问题?
  • 我该如何解决这个问题?
  • 有没有办法缓冲aio_write()?我正在考虑将n_bytes加到struct aiocb的内部,传递给aio_write(),并且从aio_write_handler()内部多次呼叫aio_write()

感谢您的帮助!

+0

詹姆斯,我已经读了好几遍了,而且我还不确定你遇到了什么问题。也许它在编辑中迷路了?也许,它会帮助包含'aio_write_handler'的一些输出? –

回答

0

如果我理解正确,您在aio_error之前使用aio_return。该aio_return手册页说,

此功能只能用一次对于任何给定的请求调用,(3)返回比EINPROGRESS其他东西后 则aio_error