分享

信号和AIO

 Mytez 2017-01-18

  异步阻塞IO:阻塞通知非阻塞io,即io操作发出后不阻塞IO操作,将通知阻塞,直到采用select查询后才获得操作结果;
   异步非阻塞IO:即io操作发出后不阻塞IO操作也不阻塞通知,当操作完成后内核通过信号或回调方式主动通知调用进程,而不需要等待调用者主动进行查询。
   在异步IO操作中,当IO资源可用时驱动释放相应的信号给调用进程;当调用者捕获到信号后执行相关的信号处理函数;对于应用程序需通过fcntl(fd,F_SETOWN,getpid())将该进程设定为操作资源(文件)的属主以确定信号的接受对象,通过fcntl(fd,F_SETFL,FASYNC)设置FASYNC 调用驱动的fasync函数;待资源可使用时kill_fasync函数释放信号给调用者。
   AIO 的基本思想是允许进程发起很多 I/O 操作,而不用阻塞或等待任何操作完成。稍后或在接收到 I/O 操作完成的通知时,进程就可以检索 I/O 操作的结果;对于一系列的IO操作是使用lio_list函数发起的,先定义一个aiocb的指针数组后于之即可发起;AIO可以使用信号或回调函数作为资源可用通知。
struct sigaction
  {
  __sighandler_t sa_handler; //信号处理函数地址 *阻塞的意思是延迟相应信号
  unsigned long sa_flags; //信号的处理标志:
  //SA_NODEFER表示内核不阻塞信号,一般为阻塞信号
  //SA_RESETHAND:表示调用信号处理函数重置为缺省态
  //SA_SIGINFO:表示处理函数有三个参数;void (*_sa_sigaction)(int,struct siginfo *,void *)因为对于应用层而言处理函数为 union {__sighandler_t _sa_handler; void (*_sa_sigaction)(int, struct siginfo *, void *);} _u;
  __sigrestore_t sa_restorer; //保存地址
  sigset_t sa_mask; //指定哪些信号被阻塞,一般默认为当前信号被阻塞


};
  
struct aiocb {
   int aio_fildes; //aio文件描述符
   int aio_lio_opcode;//进行批量IO操作时有效,读写类型
   volatile void *aio_buf;//数据缓冲
   size_t aio_nbytes; //数据缓冲长度
   int aio_reqprio;//信号优先级
   struct sigevent aio_sigevent; //aio结束后该执行的操作
   /* Internal fields */
};
  
struct sigevent {
  union sigev_value{int sival_int;void *sival_ptr;}
  //信号传递值,即信号传递为处理函数的信息;
   若函数为独参时为信号值
   若为三个参数时则将包含aiocb结构体的siginfo _t传递给函数以完成AIO的异步读写。
  int sigev_signo; //信号值(类型)
  int sigev_notify; //通知模式SIGEV_SIGNAL为信号,SIGEV_THREAD为回调函数
  union {
   int _pad[SIGEV_PAD_SIZE];
   int _tid; //使用宏定义sigev_notify_thread_id 线程ID号
   struct {
   void (*_function)(sigval_t); //使用宏定义sigev_notify_function为线程回调函数
   void *_attribute; //使用宏定义sigev_notify_attributes为线程属性
   } _sigev_thread;
   } _sigev_un;
};
  
使用范例:


//初始化信号                                                                                


sig_act.sa_mask=0;                                                 


sig_act.sa_flags= SA_SIGINFO; //信号传递aiobc    //--------------------------------------------------


使用3参数;                                                                                          


sig_act. sa_sigaction=fun;//信号处理函数                  //---------------------------------------------------                        


                                                                            


//初始化aiocb结构


my_aiocb. aio_fildes=fd;


my_aiocb. aio_buf=***;


my_aiocb. aio_nbytes=N;


my_aiocb. aio_offset=next_offset;


//表示下一个操作从上一个操作结束处开始


//AIO请求于与信号处理函数链接                               //AIO请求于与回调线程处理函数链接


my_aiocb. aio_sigevent. sigev_notify=SIGEV_SIGNAL;     my_aiocb. aio_sigevent. sigev_notify=SIGEV_THREAD;


//表示以信号作通知                                          //表示以回调线程作通知


my_aiocb. aio_sigevent. sigev_signo=SIGIO;        my_aiocb. aio_sigevent. sigev_notify_function=fun1;//回调函数


                                                                        my_aiocb. aio_sigevent. sigev_notify_attributes=NULL;//属性不使用


my_aiocb. aio_sigevent. sival_ptr=&my_aiocb;      my_aiocb. aio_sigevent. sival_ptr=&my_aiocb;


 


//捕获信号


sigaction(SIGIO,&sig_act,NULL);                      //--------------------------------------------------               


 


//信号处理函数                                                      // 回调函数


void funint signo,siginfo_t *info,void *context     void fun1sigval_t sigval


{-----------------------------p=info->si_value.sival_ptr;      {-----------------------------p=sigval.sival_ptr;


//获得aiobc地址                                                           //获得aiobc地址


}                                                                              }   


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多