libaio 的 Asynchronous I/O 测试代码

需要libaio libaio-devel的包,到http://rpm.pbone.net/index.php3去下

 

 

这是模仿libaio-oracle写的,哪位好人去做个测试,把结果发上来,最好能和glibc的在相同环境下对比对比

代码如有不对的地方,请指出

 

 

 

 

 

#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 be 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 block 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;

    /* Thanks 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) 
  {
/*
             * Note that this relative timeout is currently not
             * adjusted.  This means that each time around the loop
             * a full timeout is incurred.  Hopefully the kernel will
             * soon adjust the timeout when it returns.  Otherwise,
             * aio_suspend() and aio_reap() will 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;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值