在Ubuntu 16.04.1 LTS上测试Linux AIO功能实录

前端之家收集整理的这篇文章主要介绍了在Ubuntu 16.04.1 LTS上测试Linux AIO功能实录前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

我们知道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

猜你在找的Ubuntu相关文章