Linux设备驱动程序之异步通知与异步I/O(四)
时间:2010-10-23 来源:☆&寒 烟☆
"啊?那我咋知道,你说的我能记住就不错了,让我发明创造,我可是不会."小王委屈道。
“笨死了,我前边花了那么多的时间来讲信号之类的东西,联想一下信号作为异步通知的信号,也想的出来啊,告诉你,我当年用脚肢头都能想到,可你..真让我失望”我叹气到,“算了,也不怪你了,咱们开始继续学习吧“。
先上代码:使用信号作为AIO异步IO通知机制
void setup_io(..) { int fd; struct sigaction sig_act; struct aiocb my_aiocb; ... //设置信号处理函数 sigemptyset(&sig_act.sa_mask); sig_act.sa_flags = SA_SIGINFO; sig_act.sa_sigaction = aio_completion_handler; //设置AIO请求 bzero((char *)&my_aiocb, sizeof(struct aiocb)); my_aiocb.aio_flags = fd; my_aiocb.aio_buf = malloc(BUF_SIZE + 1); my_aiocb.aio_nbytes = BUF_SIZE; my_aiocb.offset = next_offset; //连接AIO请求和信号处理函数 my_aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNVAL; my_aiocb.aio_sigevent.sigev_signo = SIGIO; my_aiocb.aic_sigevent.sigev_value.sival_ptr = &my_aiocb; //将信号和处理函数绑定 ret = sigaction(SIGION, &sig_act, NULL); ... ret = aio_read(&my_aiocb); } //信号处理函数 void aio_completion_handler(int signo, siginfo_t *info, void *context) { struct aiocb *req; //确定是我们需要的信号 if(info->si_signo == SIGIO) { req = (struct aiocb *)info->si_value.sival_ptr; //获得aiocb; //请求的操作是否完成 if(aio_error(req) ==0 ) { ret = aio_return(req); } } return ; }从上边可以看到,使用AIO的应用程序同样需要定义信号处理函数,在指定的信号被产生时会触发调用这个处理程序。
“那么是不是就只能使用信号这种方式呢,我记得以前没一个知识点你都给我讲了好多方法,这个歌也不例外吧”小王说。
“嗯,真聪明,就喜欢聪明的女生”听到小王也懂得开动脑子了,我也要表示表示不是。
再上代码:使用回调函数最为AIO的通知
void setup_io(..) { ...//同上 //连接AIO请求和线程回调函数 my_aiocb.aio_sigevent.sigev_notify = SIGEV_THREAD; my_aiocb.aio_sigevent.notify_function = aio_completion_handler; //设置回调函数 my_aiocb.aio_sigevent.notify_attributes = NULL; my_aiocb.aio_sigevent.sigev_value.sival_ptr = &my_aiocb; ... ret = aio_read(&my_aiocb); } //信号处理函数 void aio_completion_handler(int signo, siginfo_t *info, void *context) { struct aiocb *req; req = (struct aiocb *)sigval.sival_ptr; //获得aiocb; //请求的操作是否完成 if(aio_error(req) ==0 ) { ret = aio_return(req); } return ; }
上述程序在创建aiocb请求之后,使用SIGEV_THREAD请求了一个线程回调函数作为通知方法。在回调函数中。通过(struct aiocb *)info->si_value.sival_ptr可以获得对应的aiocb指针,使用AIO函数可验证请求是否已经完成。
“不过,小王,对不起哈,没想到一说就收不住了,这节也只是讲了有关的应用,下节咱们开始讲讲AIO与驱动设备,回归驱动主题”。
相关阅读 更多 +