지금 프로젝트에서 작성한 프로그램의 개선점을 찾다보니, 비동기 작업 처리를 위해 aio를 이용하면 좋을듯 하다.
아래 사이트 내용을 참조하여 완전한 예제로 구성해보았다.
http://www.ibm.com/developerworks/linux/library/l-async/
컴파일은 gcc -lrt -o aioTest aioTest.c 으로 수행.
file.txt 내용은 다음과 같다.
123456789abcdefghijklmnopqrstuvwxyz
//aioTest.c
#include <aio.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
// gcc -lrt -o aioTest aioTest.c
// librt" stands for "real time library".
//////////////////////////////////////////////////////////////////
// busy-wait until the status changes
void testBusyWait()
{
printf("\n\n==================================================\n");
int fd, ret;
//int BUFSIZE = 10240;
int BUFSIZE = 5;
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; //the first offset in the file
//below block aio /////////////////////////////////
int MAX_LIST = 1;
struct aioct *cblist[MAX_LIST];
/* Clear the list. */
bzero( (char *)cblist, sizeof(cblist) );
/* Load one or more references into the list */
cblist[0] = &my_aiocb;
//below block aio /////////////////////////////////
ret = aio_read( &my_aiocb );
//below block aio /////////////////////////////////
ret = aio_suspend( cblist, MAX_LIST, NULL );
//below block aio /////////////////////////////////
if (ret < 0) perror("aio_read");
while ( aio_error( &my_aiocb ) == EINPROGRESS ) {
printf("busy waiting...\n");
}
if ((ret = aio_return( &my_aiocb )) > 0) {
/* got ret bytes on the read */
printf("ret [%d]\n", ret);
//print buffer
printf("buff[%s]\n",my_aiocb.aio_buf);
} else {
/* read failed, consult errno */
printf("read failed\n");
}
}
//////////////////////////////////////////////////////////////////
// lio_listio , Initiate a list of I/O operations
// with busy waiting
void testListio()
{
printf("\n\n==================================================\n");
int fd, ret;
//int BUFSIZE = 10240;
int BUFSIZE = 5;
int MAX_LIST = 2;
struct aiocb aiocb1, aiocb2;
struct aiocb *list[MAX_LIST];
fd = open( "file.txt", O_RDONLY );
if (fd < 0) perror("open");
/* Zero out the aiocb structure (recommended) */
bzero( (char *)&aiocb1, sizeof(struct aiocb) );
bzero( (char *)&aiocb2, sizeof(struct aiocb) );
//aiocb1
aiocb1.aio_fildes = fd;
aiocb1.aio_buf = malloc(BUFSIZE+1);
aiocb1.aio_nbytes = BUFSIZE;
aiocb1.aio_offset = 0; //the first offset in the file
aiocb1.aio_lio_opcode = LIO_READ;
//aiocb2
aiocb2.aio_fildes = fd;
aiocb2.aio_buf = malloc(BUFSIZE+1);
aiocb2.aio_nbytes = BUFSIZE;
aiocb2.aio_offset = BUFSIZE; //!!!
aiocb2.aio_lio_opcode = LIO_READ;
bzero( (char *)list, sizeof(list) );
list[0] = &aiocb1;
list[1] = &aiocb2;
//WAIT
//ret = lio_listio( LIO_WAIT, list, MAX_LIST, NULL );
// NO_WAIT
ret = lio_listio( LIO_NOWAIT, list, MAX_LIST, NULL );
while ( aio_error( &aiocb1 ) == EINPROGRESS ||
aio_error( &aiocb2 ) == EINPROGRESS )
{
printf("busy waiting...\n");
}
// NO_WAIT
//aiocb1
if ((ret = aio_return( &aiocb1 )) > 0) {
printf("\n******\n");
printf("aiocb1 ret [%d]\n", ret);
printf("aiocb1 buff[%s]\n",aiocb1.aio_buf);
} else {
/* read failed, consult errno */
printf("aiocb1 read failed\n");
}
//aiocb2
if ((ret = aio_return( &aiocb2 )) > 0)
{
printf("\n******\n");
printf("aiocb2 ret [%d]\n", ret);
printf("aiocb2 buff[%s]\n",aiocb2.aio_buf);
} else {
/* read failed, consult errno */
printf("aiocb2 read failed\n");
}
}
//////////////////////////////////////////////////////////////////
//aio with callback
//also available : Asynchronous notification with signals
struct aiocb my_aiocb;
void aio_completion_handler( sigval_t sigval )
{
printf("aio_completion_handler\n");
struct aiocb *req;
req = (struct aiocb *)sigval.sival_ptr;
/* Did the request complete? */
if (aio_error( req ) == 0) {
/* Request completed successfully, get the return status */
int ret = aio_return( req );
printf("ret [%d]\n", ret);
printf("buff[%s]\n",req->aio_buf);
}
return;
}
void testCallback()
{
printf("\n\n==================================================\n");
int fd, ret;
//int BUFSIZE = 10240;
int BUFSIZE = 20;
fd = open( "file.txt", O_RDONLY );
if (fd < 0) perror("open");
/* Set up the AIO request */
bzero( (char *)&my_aiocb, sizeof(struct aiocb) );
my_aiocb.aio_fildes = fd;
my_aiocb.aio_buf = malloc(BUFSIZE+1);
my_aiocb.aio_nbytes = BUFSIZE;
my_aiocb.aio_offset = 0;
/* Link the AIO request with a thread callback */
my_aiocb.aio_sigevent.sigev_notify = SIGEV_THREAD;
my_aiocb.aio_sigevent.sigev_notify_function = aio_completion_handler;
my_aiocb.aio_sigevent.sigev_notify_attributes = NULL;
my_aiocb.aio_sigevent.sigev_value.sival_ptr = &my_aiocb;
ret = aio_read( &my_aiocb );
}
//////////////////////////////////////////////////////////////////
int main(int argc,char** argv)
{
testBusyWait();
testListio();
testCallback();
while(1) {
sleep(1);
}
}
수행 결과는 다음과 같다.
==============================================================
ret [5]
buff[12345]
==============================================================
aiocb1 busy waiting...
aiocb1 busy waiting...
.....
aiocb1 busy waiting...
******
aiocb1 ret [5]
aiocb1 buff[12345]
******
aiocb2 ret [5]
aiocb2 buff[6789a]
==============================================================
aio_completion_handler
ret [20]
buff[123456789abcdefghijk]