나는 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()
을 호출하는 것으로 생각했다.
도움 주셔서 감사합니다.
제임스,이 여러 번 읽었는데, 아직도 어떤 문제가 발생하고 있는지 잘 모르겠습니다. 편집에서 길을 잃은 것일까 요? 아마도,'aio_write_handler'의 출력물을 포함 시키는데 도움이 될까요? –