Need Libaio libaio-devel bag, go to http://rpm.pbone.net/index.php3.
This is imitate Libaio-oracle writes, which good person goes to do a test, sends out the result, best can compare with glibc in the same environment
If there is something wrong with the code, please point out
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <libaio.h>
#define IOCB_CMD_READ 0
#define Iocb_cmd_write 1
#define IOCB_CMD_NOP 2
#define IOCB_CMD_CANCEL 3
#define IOCB_CMD_FSYNC 4
#define IOCB_CMD_FDSYNC 5
#define Iocb_cmd_running 6
#define Iocb_cmd_done 7
#define MAX_EVENTS 512
#define MAX_AIO_REAP Max_events
#define AIO_DATA Data
#define DATA_FROM_REQ (R) ((void *) (R))
#define REQ_FROM_DATA (d) ((Aiorequest *) (d))
#define MAX_IO_QUEUE 1024
#define AIOCB aiocb64
#define Aio_read AIO_READ64
#define Aio_write Aio_write64
#define AIO_ERROR Aio_error64
#define Aio_return Aio_return64
#define Aio_suspend AIO_SUSPEND64
struct AIOCB64 {
int aio_fildes; /* File Desriptor. */
Short Aio_lio_opcode; /* Operation to be performed. */
Short Aio_reqprio; /* Request priority offset. */
void *aio_buf; /* Location of buffer. */
size_t Aio_nbytes; /* Length of transfer. */
int aio_offset; /* File offset. */
/* These are internal to the KERNEL/LIBC. */
Long __aio_key; Kernel sets this to-1 if completed
Otherwise >= 0 (the request#)
void * __AIO_DATA; Pointer to is returned in event ' s data
int __error_code;
};
Enum
{
Lio_read,
#define Lio_read Lio_read
Lio_write,
#define Lio_write Lio_write
Lio_nop,
#define LIO_NOP Lio_nop
Lio_poll,
#define Lio_poll Lio_poll
};
Enum
{
Aio_canceled,
#define Aio_canceled aio_canceled
Aio_notcanceled,
#define Aio_notcanceled aio_notcanceled
Aio_alldone
#define Aio_alldone Aio_alldone
};
Enum
{
Lio_wait,
#define LIO_WAIT lio_wait
Lio_nowait
#define LIO_NOWAIT lio_nowait
};
typedef struct _AIOREQUEST aiorequest;
Enum
{
aior_unused = 0,/* Unused control block * *
Aior_in_progress = 0xbeef,/* in PROGRESS I/O *
Aior_complete = 0xdead,/* Completed I/O
};
struct _aiorequest
{
struct IOCB IOCB; /* Control blocks sent to kernel * *
struct AIOCB64 *AIOCB; /* User ' s control block * *
};
Static io_context_t Aio_context;
static int _aio_rw (int op, struct aiocb64 * aiocbp);
int Aio_init ()
{
if (Io_queue_init (Max_io_queue, & (Aio_context))
return-1;
return (0);
}
int aio_read64 (struct aiocb64 *aiocbp)
{
int RC;
if (AIOCBP = NULL)
{
errno = einval;
Return (-1);
}
rc = _AIO_RW (Lio_read, AIOCBP);
Return (RC > 1? 0:-1);
}
int aio_write64 (struct aiocb64 *aiocbp)
{
int RC;
struct AIOCB64 *aiocbs[] = {NULL};
if (AIOCBP = NULL)
{
errno = einval;
Return (-1);
}
Aiocbs[0] = AIOCBP;
rc = _AIO_RW (Lio_write, AIOCBP);
Return (RC > 1? 0:-1);
}
Static long aior_get_events (struct timespec *timeout)
{
struct Io_event events[max_events];
int i;
LONG ret;
Aiorequest *req;
/* For no compat defines in Libaio.h * *
#ifdef Old_libaio
ret = io_getevents (Aio_context, max_events, EVENTS, timeout);
#else
ret = Io_getevents (Aio_context, 1, max_events, EVENTS, timeout);
#endif/* Old_libaio * *
if (Ret < 0)
return (ret);
else if (ret = 0)
return (0);
for (i = 0; i < ret; i++)
{
req = Req_from_data (events[i].data);
Req->aiocb->__error_code = Events[i].res;
if (Req->aiocb->__aio_key!= aior_in_progress)
{
printf ("AIOR_GET_EVENTS:AIOCB at%p has __aio_key%ld!/n", REQ->AIOCB, Req->aiocb->__aio_key);
Continue
}
Req->aiocb->__aio_key = Aior_complete;
printf ("Aior_get_events:collected AIOCB at%p/n", REQ->AIOCB);
}
return (ret);
}
int aio_error64 (struct aiocb64 *aiocbp)
{
int ret;
struct Timespec to = {0, 0};
if (AIOCBP = NULL)
{
errno = einval;
Return (-1);
}
if (Aiocbp->__aio_key = = Aior_complete)
{
Aiorequest *req = Req_from_data (Aiocbp->__aio_data);
if (NULL!= req)
{
Aiocbp->__aio_data = NULL;
Free (req);
}
if (Aiocbp->__error_code < 0)
Return (-(Aiocbp->__error_code));
Else
return (0);
}
/* Do we have an invalid __aio_key? */
if (Aiocbp->__aio_key!= aior_in_progress)
{
errno = einval;
Return (-1);
}
ret = aior_get_events (&to);
if (Ret < 0)
{
errno =-ret;
Return (-1);
}
/*
* Aior_complete_free really shouldn ' t happen here, but it
* doesn ' t hurt.
*/
if (Aiocbp->__aio_key = = Aior_complete)
{
printf ("AIO_ERROR:AIOCB at%p complete/n", AIOCBP);
Aiorequest *req = Req_from_data (Aiocbp->__aio_data);
if (NULL!= req)
{
Aiocbp->__aio_data = NULL;
Free (req);
}
if (Aiocbp->__error_code < 0)
Return (-(Aiocbp->__error_code));
Else
return (0);
}
return (einprogress);
}
int Aio_return64 (struct aiocb64 *aiocbp)
{
Return Aio_error64 (AIOCBP);
}
int aio_suspend64 (/*const*/struct aiocb64 * const list[], int nent,
const struct TIMESPEC *timeout)
{
struct Timespec mod_timeout;
Aiorequest * REQ;
int ret = 0;
int done = 0, I;
/* Get round constness * *
if (timeout)
memcpy (&mod_timeout, timeout, sizeof (mod_timeout));
while (done = = 0)
{
for (i = 0; i < nent; i++)
{
if ((List[i]!= NULL) && ((List[i]->__aio_key = = Aior_complete))
{
ret = 0;
Done = 1;
req = Req_from_data (list[i]->__aio_data);
if (NULL!= req)
{
List[i]->__aio_data = NULL;
Free (req);
}
Break
}
}
if (done = = 0)
{
/*
* This this relative timeout be currently not
* Adjusted. This means the around the loop
* A full timeout is incurred. Hopefully the kernel would
* Soon adjust the timeout when it returns. Otherwise,
* Aio_suspend () and Aio_reap () 'll have to do
* Gettimeofday () tricks to make it work right.
*/
ret = aior_get_events (timeout &mod_timeout:null);
if (ret =-etimedout) | | (ret = 0))
{
errno = Eagain;
ret =-1;
Done = 1;
}
}
}
return (ret);
}
static int _aio_rw (int op, struct aiocb64 * PAIOCB)
{
Aiorequest *req;
struct IOCB **iocbpp;
int I, ret;
int retrycount = 0;
if (PAIOCB = NULL)
Return-einval;
Req = (Aiorequest *) malloc (sizeof (aiorequest) + sizeof (struct IOCB *));
if (req = NULL)
Return-eagain;
Else
memset (req, 0, (sizeof (aiorequest) + sizeof (struct IOCB *)));
IOCBPP = (struct IOCB * *) (req + 1);
REQ->AIOCB = PAIOCB;
Paiocb->__aio_data = req;
Paiocb->__aio_key = aior_in_progress;
Iocbpp[0] = & (REQ->IOCB);
Switch (OP)
{
Case Lio_read:
Io_prep_pread (& (REQ->IOCB), Paiocb->aio_fildes, Paiocb->aio_buf, Paiocb->aio_nbytes, paiocb-> Aio_offset);
Break
Case Lio_write:
Io_prep_pwrite (& (REQ->IOCB), Paiocb->aio_fildes, Paiocb->aio_buf, Paiocb->aio_nbytes, paiocb-> Aio_offset);
Break
Default
Return-einval;
}
Req->iocb.aio_data = Data_from_req (req);
ret = Io_submit (Aio_context, 1, IOCBPP);
if (-eagain = ret)
{
ret = Io_submit (Aio_context, 1, IOCBPP);
}
if (Ret < 0)
{
errno =-ret;
ret =-1;
}
return ret;
}
const int data_len = 8192;
const int data_size = 50000;
Char bufferao[8192] __attribute__ ((aligned (4096)));
void Testlibaio ()
{
struct timeval start;
struct Timeval end;
int ret;
int i = 0;
int dwflags = O_RDWR | O_largefile | O_direct | O_sync | O_creat | O_EXCL; //| O_noatime
dwflags = O_rdwr | O_largefile | O_sync | O_creat | O_EXCL;
int fd = open ("Libaio_write.dat", dwflags);
if (fd<0)
{
Perror ("Open error:");
Return
}
if (Ftruncate64 (FD, Data_len * data_size))
{
Perror ("Ftruncate64 error:");
Return
}
Aio_init ();
Gettimeofday (&start, NULL);
for (; i<= data_size; i++)
{
struct AIOCB Staio;
memset (Bufferao, i%128, Data_len);
memset (&staio, 0, sizeof (Staio));
Staio.aio_buf = Bufferao;
Staio.aio_nbytes = Data_len;
Staio.aio_offset = i * data_len;
Staio.aio_fildes = FD;
ret = Aio_write (&staio);
if (Ret < 0)
{
Perror ("Libaio_write error:");
Return
}
struct AIOCB *cblist[1] = {&staio};
ret = Aio_error (&staio);
if (ret = 0) {
Already completed
}
else if (ret = = einprogress) {
if (aio_suspend (/*const*/struct AIOCB *const*) cblist, 1, NULL)
{
Perror ("Libaio_suspend error:");
Return
}
}
else {
Perror ("Libaio_error error:");
Return
}
/*
if (Aio_return (&staio)!= Data_len)
{
Perror ("Libaio_return error:");
Return
}
*/
}
Gettimeofday (&end, NULL);
Close (FD);
printf ("/nlibaio o_direct Second:%d microsec:%d/n", End.tv_sec-start.tv_sec, end.tv_usec-start.tv_usec);
}
int main ()
{
Testlibaio ();
return 1;
}