2016-12-08 9 views
0

나는 sendfile(2)의 기능을 본질적으로 aio_read(3)aio_write(3)을 사용하여 비동기식으로 모방하려고합니다.대용량 파일에 대한 aio_write

큰 파일 (> 150k)을 테스트하는 것을 제외하면 모든 것이 잘 작동하는 것처럼 보입니다.

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 핸들러에서 캡처 : 나는 aio_read() 전화를 구축,

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

첫째 :

나는 내가 이전의 트랙을 유지하기 위해 사용하고 간단한 struct io_request가 :

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 핸들러에서 캡처 :이 시점 aio_write()에서

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"); 
     } 
    } 
} 

이 완료되어 있어야합니다. 나는 반환 값을 확인하고 이에 따라 행동한다. 두 호출 모두 적절한 바이트 수가 기록되었다고보고하며 쓰기 도중 오류가 발생하지 않습니다.

큰 응용 프로그램은 HTTP 서버입니다. 원격 클라이언트가 aio_write()을 따라 잡을만큼 충분히 빨리 읽을 수 없기 때문에이 문제가 발생한다고 추측합니다. 이 sendfile() 구현을했을 때 파일 전송을 완료하려면 sendfile() 번을 여러 번 호출해야했습니다.

몇 가지 직접적인 질문 :

  • aio_return()aio_error() 어떤 문제를보고하지 않는 이유는 무엇입니까?
  • 어떻게하면이 문제를 해결할 수 있습니까?
  • 버퍼링 할 방법이 있습니까 aio_write()? 나는 을 aio_write()에 전달하고, aio_write()을 여러 번 호출하여 aio_write_handler()을 호출하는 것으로 생각했다.

도움 주셔서 감사합니다.

+0

제임스,이 여러 번 읽었는데, 아직도 어떤 문제가 발생하고 있는지 잘 모르겠습니다. 편집에서 길을 잃은 것일까 요? 아마도,'aio_write_handler'의 출력물을 포함 시키는데 도움이 될까요? –

답변

0

정확하게 이해하면 aio_returnaio_error 앞에 사용하고 있습니다. aio_return 매뉴얼 페이지 (3) EINPROGRESS이 아닌 다른 뭔가를 반환 aio_error

이 기능은 단 한번 주어진 요청에 대해 호출 할 필요가 말했다.