linux 原生aio API详解

如下:

extern int io_setup(int maxevents, io_context_t *ctxp);
extern int io_destroy(io_context_t ctx);
extern int io_submit(io_context_t ctx, long nr, struct iocb *ios[]);
extern int io_cancel(io_context_t ctx, struct iocb *iocb, struct io_event *evt);
extern int io_getevents(io_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct timespec *timeout);

io_setup函数:

此系统调用用于创建一个同步io环境,可以同时处理maxevents个操作,ctxp必须初始化为0,io_setup会自动分配填充空间,所以,调用后一定要掉用io_destroy进行释放掉。

返回值:

成功为0,失败为以下值

EAGAIN:maxevents已经超过个系统用户的限制,即文件/proc/sys/fs/aio-max-nr中的数字

EFAULT:分配给ctxp的指针无效

EINVAL:ctxp未初始化为0或者maxevents超限。

ENOMEM:内核资源不足。(说明系统压力大)

ENOSYS:未实现此系统调用

io_destroy函数:

释放io_setup创建的异步io环境,系统调用将尝试取消针对ctx_id的所有未完成的异步I/O操作,阻塞在不能不取消的操作上直到操作完成。

返回值:

成功为0,失败为以下值

EFAULT:分配给ctxp的指针无效

EINVAL:分配给ctxp的指针无效

ENOSYS:未实现此系统调用

 

io_submit函数:提交事件

将ios设置的事件,提交到ctx队列中,等待事件排队处理。

返回值:

成功:0~nr

EAGAIN:系统内资源不够用。

EBADF:提交的文件描述符不对,可能是不支持异步操作的文件描述符或者无用已关闭的文件描述符。

EFAULT:某一部分指针无效

EINVAL:参数有问题,检查参数设置。

 

io_cancel函数:

io_cancel()系统调用试图取消以前用io_submit(2)提交的异步I/O操作。iocb参数描述要取消的操作,ctx参数是提交操作的异步环境上下文。如果操作被成功取消,则事件将被复制到由结果指向的内存中,而不会被放到完成队列中。

返回值:

成功0,失败如上

io_getevents函数:

io_getevents系统调用读取ctx异步环境中至少min_nr至多nr个事件,(前提是timeout为NULL阻塞到至少符合条件数目的事件,如果设置超时,则在一定的时间后返回)

返回值:成功则为完成的事件,0则表示没有完成的事件。失败如上。

完整示例如下:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <libaio.h>
#include <sys/stat.h>
#include <fcntl.h> 
#include <errno.h> 


#define MYLOG(iRet)		fprintf(stderr,"%s %d %s \n",__FILE__,__LINE__,strerror(iRet))
#define	AIO_MAX				64

int 			filefd1;
int 			filefd2;
int 			globle=0;

void wt_func(io_context_t ctx, struct iocb *iocb, long res, long res2 )
{
		
}

void rd_func( io_context_t ctx, struct iocb *iocb, long res, long res2 )
{
	globle++;
	if (  ((char *)(iocb->u.c.buf))[0] != '\0' )
		printf("读取:[%s][%d] %s\n",(char *)iocb->u.c.buf,globle,__func__);
		
}

int main(){
	int 			iRet=0;
	unsigned 	nr_events;
	unsigned	aiobufsize;
	long long offset;
	char		*	aiobuf;
	int 			eventnum;
	int 			ievent;
	int				isubmit=0;
	int				filesize =0 ;
	struct stat 			file1stat;
	struct 	iocb 	* 	iocpp[AIO_MAX];
	io_context_t  	ctx_idp;
	struct io_event 	events[AIO_MAX];
	io_callback_t 		cb;
	struct iocb 	*		aio;
	
	
	
	nr_events		=	AIO_MAX;
	
	filefd1 = open("./aio.txt",O_RDWR,0666);
	if ( filefd1 == -1 )
	{
			MYLOG(errno);
			exit(errno);
	}
	
	filefd2 = open("./aio2.txt",O_RDWR,0666);
	if ( filefd2 == -1 )
	{
			MYLOG(errno);
			exit(errno);
	}
	
	iRet = fstat(filefd1,&file1stat);
	if ( iRet )
	{
			MYLOG(iRet);
			exit(iRet);
	}
	
	aiobufsize 	= (file1stat.st_size-(file1stat.st_size%4))/4 ;
	filesize		=	file1stat.st_size;
	isubmit = 4+1;
	
	
	int memnum  = 0;
	for (memnum =0  ;memnum<AIO_MAX; memnum++ )
	{
			iocpp[memnum] = ( struct 	iocb 	*)malloc(sizeof(struct 	iocb 	) );
		
	}
	
	offset		=	0;
	
	iRet=io_queue_init(nr_events,&ctx_idp);   
	//iRet=io_setup(nr_events,&ctx_idp);
	if ( iRet )
	{	
		MYLOG(iRet);
		exit(iRet);
	}
	
	
	int submittemp;
	for ( submittemp=0;submittemp < isubmit;submittemp++)
	{
		if ( filesize <= aiobufsize   )
		{
				aiobufsize = filesize;
		}
		else
		{
				filesize = filesize - aiobufsize;
		}
		iRet = posix_memalign((void **)&aiobuf,getpagesize(), aiobufsize);
		if ( iRet )
		{
			MYLOG(iRet);
			exit(iRet);
		}
		memset(aiobuf,0x00,(size_t)sizeof(aiobuf));
		printf("提交:[%d][%p]\n",submittemp,iocpp[submittemp]);
		io_prep_pread( iocpp[submittemp],filefd1,aiobuf,aiobufsize,offset );
		io_set_callback(iocpp[submittemp],rd_func);
		iRet = io_submit(ctx_idp, 1, &iocpp[submittemp]);
  	if ( iRet < 0 ) 
  	{		       
    	MYLOG(iRet);
			exit(iRet);
  	}
  	printf("读取:[%s][%d][%lld][%p][%p]\n",(char *)iocpp[submittemp]->u.c.buf,globle,offset,iocpp[submittemp]->u.c.buf,aiobuf);
		offset = offset + aiobufsize;
		
  }
  
  
	eventnum = io_getevents(ctx_idp,1,AIO_MAX,events,NULL);
	if ( eventnum < 0 )
	{
			MYLOG(iRet);
			exit(iRet);	
	}
	printf("\n得到事件:[%d]\n",eventnum);
	for ( ievent=0 ;ievent<eventnum;ievent++ )
	{
		aio	=	NULL;
		cb	=	(io_callback_t) events[ievent].data;	
		aio = events[ievent].obj;
		
			printf("事件:[%d][%p] [%p]\n",ievent,aio,&events[ievent]);
		
		cb(ctx_idp, aio, events[ievent].res, events[ievent].res2);/*调用设置的rd_func函数*/
	}
	for (memnum =0  ;memnum<AIO_MAX; memnum++ )
	{
			free(iocpp[memnum]);
	}
	free(aiobuf);
	io_destroy(ctx_idp);
	printf("总共调用:%d \n",globle);
	return 0;
}

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux中关闭AIO(异步输入输出)可以通过以下步骤实现: 1. 首先,确保在程序中调用了`aio_cancel`函数来取消所有未完成的异步操作。这将确保在关闭AIO之前,所有的异步操作都被终止。 2. 然后,使用`aio_error`函数来检查异步操作的错误状态。如果返回值为`EINPROGRESS`,表示异步操作仍在进行中,需要等待操作完成。 3. 使用`aio_return`函数来获取异步操作的返回值。如果返回值大于0,表示操作已完成,并且可以获取到返回的数据。 4. 最后,使用`aio_suspend`函数来等待所有异步操作完成。这将阻塞程序,直到所有异步操作都完成。 5. 在所有异步操作都完成后,可以关闭文件描述符和释放相关的资源。 以下是一个示例代码,展示了如何关闭AIO: ```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <aio.h> #include <fcntl.h> int main() { struct aiocb cb = {0}; int fd = open("test.txt", O_RDONLY); if (-1 == fd) { printf("文件打开失败:%m\n"); exit(-1); } printf("文件打开成功!\n"); // 异步读取文件数据 cb.aio_fildes = fd; cb.aio_nbytes = BUFF_SIZE; cb.aio_offset = 0; int r = aio_read(&cb); if (-1 == r) { printf("异步读取失败:%m\n"); close(fd); exit(-2); } printf("异步读取成功!\n"); // 取消未完成的异步操作 aio_cancel(fd, &cb); // 等待所有异步操作完成 aio_suspend(&cb, 1, NULL); // 获取异步操作的返回值 r = aio_return(&cb); if (r > 0) { printf("拿到了数据: r:%d bytes, data: %s\n", r, cb.aio_buf); } // 关闭文件描述符和释放内存 close(fd); free(cb.aio_buf); return 0; } ``` 请注意,以上代码仅展示了关闭AIO的基本步骤,并不包含完整的错误处理和资源释放。在实际应用中,需要根据具体情况进行适当的错误处理和资源管理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值