异步IO写文件的方法

函数解析:
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则表示没有完成的事件。失败如上。


代码示例(用来测试异步IO落盘速度)

#include <stdio.h>
#include <time.h>
#include <pthread.h> 
#include <unistd.h> /* for syscall() */ 
#include <sys/syscall.h> /* for __NR_* definitions */ 
#include <linux/aio_abi.h> /* for AIO types and constants */ 
#include <fcntl.h> /* O_RDWR */ 
#include <string.h> /* memset() */ 
#include <inttypes.h>
#include <sys/time.h>
#include <stdlib.h>


#define COUNT_PTHREAD 8
#define value_SIZE 4*1024*1024UL
#define COUNT_VALUE 256
#define COUNT_LOOP  10


static    uint8_t * value = NULL;


inline int io_setup(unsigned nr, aio_context_t *ctxp) 
{ 
    return syscall(__NR_io_setup, nr, ctxp); 
} 

inline int io_destroy(aio_context_t ctx) 
{ 
    return syscall(__NR_io_destroy, ctx); 
} 

inline int io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp) 
{ 
    return syscall(__NR_io_submit, ctx, nr, iocbpp); 
}

inline int io_getevents(aio_context_t ctx, long min_nr, long max_nr, struct io_event *events, struct timespec *timeout) 
{ 
    return syscall(__NR_io_getevents, ctx, min_nr, max_nr, events, timeout);
} 




static uint32_t get_now_time(char * data ,uint32_t channle_id)
{
    
        static uint32_t cnt = 0;
        struct timeval tv;
        char time[60]={0};
    gettimeofday(&tv, NULL);
    strftime(time,60,"%Y-%m-%d-%H-%M-%S",localtime(&tv.tv_sec));
    sprintf(data,"/data/brickmd0p1/CH%d-%s-%3d-%d.dat",channle_id,time ,(int)(tv.tv_usec / 1000),cnt++);
        printf("get_now_time\n");
    return 0;
}



int * openfile(void)
{
    int i;
    char value[100] = {0};
    int fd[COUNT_PTHREAD];
    
    fd = (int *)malloc(sizeof(int) * COUNT_PTHREAD);
    if(fd == NULL)
        return NULL;
    for(i = 0; i < COUNT_PTHREAD;i++ )
    {
        get_now_time(value,i);
        fd[i] = open(value,O_WRONLY | O_CREAT,777);
        if(fd[i] < 0)
        {
            printf("open file faild\n");
            return NULL;
        }
    }
    return fd;
    
}

void * write_file(void *s)
{
    int i;
    int ret; 
    aio_context_t ctx; 
    struct iocb cb; 
    struct iocb *cbs[1];
    int * fd  = NULL; 
    if(fd = openfile() ,fd == NULL)
            {
                return NULL;
            }
            
    ctx = 0;
    ret = io_setup(256, &ctx); 
    if (ret < 0)
  { 
        perror("io_setup error"); 
        return NULL; 
  } /* setup I/O control block */ 
    
   memset(&cb, 0, sizeof(cb));

      cb.aio_fildes = *(int*)s; 
    cb.aio_lio_opcode = IOCB_CMD_PWRITE;/* command-specific options */ 
    cb.aio_buf = (uint64_t)value; 
    cb.aio_offset = 0; 
    cb.aio_nbytes = value_SIZE; 
    cbs[0] = &cb;
    
    for(i = 0; i < COUNT_VALUE;i++)
    {
        ret = io_submit(ctx, 1, cbs);
        if (ret != 1) 
        { 
            if (ret < 0) 
                perror("io_submit error"); 
            else
                fprintf(stderr, "could not sumbit IOs"); 
            return NULL; 
        } 
        cb.aio_offset += value_SIZE;     
    }
    
    ret = io_destroy(ctx); 
    if (ret < 0)
    { 
        perror("io_destroy error"); 
        return NULL; 
    } 
    
}

int main(void)
{
    struct timeval start_t;
    struct timeval end_t;
    double total_t;
    uint32_t i =0;
        uint8_t * value1 = NULL;
    long count = 0;
    uint32_t size = 0;
    pthread_t pthread_id[COUNT_PTHREAD];
    
    
    value1 = (uint8_t *)malloc(value_SIZE);
    if(value1 == NULL)
        {
            printf("malloc faild\n");
            return -1;
        }
    value = value1;
    memset(value,0,value_SIZE);
    
        for(i=0;i<value_SIZE;i++) 
    { 
        value[i]=i%10+48; 
    } 
        
        
    gettimeofday(&start_t,NULL);
    
    
    for(i = 0; i < COUNT_PTHREAD; i++ )
    {
        pthread_create(&pthread_id[i], NULL, write_file,&fd[i]);
    }
    

    for(i = 0; i < COUNT_PTHREAD; i++ )
    {
        pthread_join(pthread_id[i], NULL);
    }
                
        gettimeofday(&end_t,NULL);
                  if(end_t.tv_usec >= start_t.tv_usec)
            total_t = (double)(end_t.tv_sec - start_t.tv_sec)+(double)(end_t.tv_usec-start_t.tv_usec)/1000000.0 ;
                  else
            total_t = (double)(end_t.tv_sec - start_t.tv_sec-1)+(double)(end_t.tv_usec+1000000.0-start_t.tv_usec)/1000000.0 ;
            printf("RECV 0 CH:--------Speed:---%lf MB/S---------\n"\
                  , (double)  value_SIZE * COUNT_PTHREAD * COUNT_VALUE/ total_t/1024/1024);
                


    for(i = 0; i < COUNT_PTHREAD; i++ )
    {
        close(fd[i]);
    }
            
    free(value1);
        
        
}

 

posted @ 2020-07-09 11:36  fc724  阅读(875)  评论(1)    收藏  举报