我们知道Nginx中有libaio这项功能,为了研究AIO的一些常用接口用法,在网上找到一个例子,异步IO读取本地文件,亲自实践了一把,记录如下:
安装依赖库
在Ubuntu 16.04上需要事先安装
apt-cache search aio
sudo apt-get install libaio1 libaio-dev
如果是CentOS,需要执行下面的命令先查询再安装
yum search libaio
yum -y install libaio libaio-devel
//description: 测试Linux的原生AIO功能演示 //refer: http://blog.chinaunix.net/uid-16979052-id-3840266.html //dependence: // sudo apt-get install libaio1 libaio-dev (Ubuntu 16.04.1) // yum -y install libaio libaio-devel (CentOS 6.x) //compile: gcc -g epoll_aio.c -o epoll_aio -laio //run: ./epoll_aio // #define _GNU_SOURCE #define __STDC_FORMAT_MACROS #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <unistd.h> #include <errno.h> #include <libaio.h> #include <sys/eventfd.h> #include <sys/epoll.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <inttypes.h> //为简单起见,需要事先从网上下载一个文件,并存放在当前目录下面, //并设置它的大小,这里选择”http://news.sohu.com/“,存为aio_sample.html #define TEST_FILE "aio_sample.html" #define TEST_FILE_SIZE 239576 #define NUM_EVENTS 128 #define ALIGN_SIZE 512 #define RD_WR_SIZE 1024 struct custom_iocb { struct iocb iocb; int nth_request; }; void aio_callback(io_context_t ctx,struct iocb *iocb,long res,long res2) { struct custom_iocb *iocbp = (struct custom_iocb *) iocb; printf ("nth_request: %d,request_type: %s,offset: %lld,length: %lu,res: %ld,res2: %ld\n",iocbp->nth_request,(iocb->aio_lio_opcode == IO_CMD_PREAD) ? "READ" : "WRITE",iocb->u.c.offset,iocb->u.c.nbytes,res,res2); } int main(int argc,char *argv[]) { int efd,fd,epfd; io_context_t ctx; struct timespec tms; struct io_event events[NUM_EVENTS]; struct custom_iocb iocbs[NUM_EVENTS]; struct iocb *iocbps[NUM_EVENTS]; struct custom_iocb *iocbp; struct epoll_event epevent; int i,j,r; void *buf; efd = eventfd(0,EFD_NONBLOCK | EFD_CLOEXEC); if (efd == -1) { perror("eventfd"); return 2; } //打开本地测试文件 fd = open(TEST_FILE,O_RDWR | O_CREAT | O_DIRECT,0644); if (fd == -1) { perror("open"); return 3; } //截断到指定大小 ftruncate(fd,TEST_FILE_SIZE); ctx = 0; if (io_setup(8192,&ctx)) { perror("io_setup"); return 4; } if (posix_memalign(&buf,ALIGN_SIZE,RD_WR_SIZE)) { perror("posix_memalign"); return 5; } printf("buf: %p\n",buf); for (i = 0,iocbp = iocbs; i < NUM_EVENTS; ++i,++iocbp) { iocbps[i] = &iocbp->iocb; io_prep_pread(&iocbp->iocb,buf,RD_WR_SIZE,i * RD_WR_SIZE); io_set_eventfd(&iocbp->iocb,efd); io_set_callback(&iocbp->iocb,aio_callback); iocbp->nth_request = i + 1; } if (io_submit(ctx,NUM_EVENTS,iocbps) != NUM_EVENTS) { perror("io_submit"); return 6; } epfd = epoll_create(1); if (epfd == -1) { perror("epoll_create"); return 7; } epevent.events = EPOLLIN | EPOLLET; epevent.data.ptr = NULL; if (epoll_ctl(epfd,EPOLL_CTL_ADD,efd,&epevent)) { perror("epoll_ctl"); return 8; } i = 0; while (i < NUM_EVENTS) { uint64_t finished_aio; if (epoll_wait(epfd,&epevent,1,-1) != 1) { perror("epoll_wait"); return 9; } if (read(efd,&finished_aio,sizeof (finished_aio)) != sizeof (finished_aio)) { perror("read"); return 10; } printf("finished io number: %" PRIu64 "\n",finished_aio); while (finished_aio > 0) { tms.tv_sec = 0; tms.tv_nsec = 0; r = io_getevents(ctx,events,&tms); if (r > 0) { for (j = 0; j < r; ++j) { ((io_callback_t) (events[j].data)) (ctx,events[j].obj,events[j].res,events[j].res2); } i += r; finished_aio -= r; } } } close(epfd); free(buf); io_destroy(ctx); close(fd); close(efd); remove(TEST_FILE); return 0; }
下面是演示结果
参考文献
原文链接:https://www.f2er.com/ubuntu/351478.html