Linux驱动开发 IO模型:异步通知IO
目录
1、异步通知IO模型是什么
2、应用程序
2.1 应用程序的步骤
2.2 应用程序编写
3、驱动程序
3.1 fasync()函数:完成发信号前的初始化
3.2 fasync_helpe()函数解析
3.3 虚拟文件系统层的实现
1、异步通知IO模型是什么
在进程中注册一个信号处理函数,如果硬件的数据准备好的时候,会产生中断,在中断处理函数中给这个进程发送信号即可。如果内核没有发出信号应用程序,不需要阻塞,运行自己特有的代码即可。
2、应用程序
2.1 应用程序的步骤
1、注册信号处理函数
signal(SIGIO,signal_handle)
2、通过fcntl调用到底层的fasync函数
flag = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, flag | FASYNC);
3、将当前进程号告诉内核
fcntl(fd,F_SETOWN,getpid());
2.2 应用程序编写
int fd;
char buf[128] = {0};void signal_handle(int signo)
{if(signo == SIGIO) {memset(buf,0,sizeof(buf));read(fd,buf,sizeof(buf)); printf("buf = %s\\n", buf);}
}int main(int argc, char argv)
{fd = open("/dev/mycdev", O_RDWR);if(signal(SIGIO,signal_handle) == SIG_ERR)PRINT_ERR("signal error");fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)|FASYNC);fcntl(fd,F_SETOWN,getpid());close(fd);return 0;
}
3、驱动程序
3.1 fasync()函数:完成发信号前的初始化
本来也要在中断处理函数中发送,此处同样的也是在write函数中发信号
ssize_t mycdev_write(struct file *file, const char __user * ubuf, size_t size, loff_t * offs)
{kill_fasync(&fapp, SIGIO, POLL_IN);
}int mycdev_fasync(int fd, struct file *file, int on)
{return fasync_helper(fd, file, on, &fapp);
}const struct file_operations fops = {.write = mycdev_write,.fasync = mycdev_fasync,
};
3.2 fasync_helpe()函数解析
int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct fapp)
{if (!on)return fasync_remove_entry(filp, fapp);return fasync_add_entry(fd, filp, fapp);
}static int fasync_add_entry(int fd, struct file *filp, struct fasync_struct fapp)
{struct fasync_struct *new;new = fasync_alloc();if (fasync_insert_entry(fd, filp, fapp, new)) {fasync_free(new);return 0;}
}struct fasync_struct *fasync_insert_entry(int fd, struct file *filp, struct fasync_struct fapp, struct fasync_struct *new)
{struct fasync_struct *fa, fp; //遍历队列,找到队尾for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) {if (fa->fa_file != filp)continue;fa->fa_fd = fd;}//填充这个结构体new->magic = FASYNC_MAGIC;new->fa_file = filp;new->fa_fd = fd;//放到队尾new->fa_next = *fapp;rcu_assign_pointer(*fapp, new);filp->f_flags |= FASYNC;
}
3.3 虚拟文件系统层的实现
SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
{ do_fcntl(fd, cmd, arg, f.file);
}static long do_fcntl(int fd, unsigned int cmd, unsigned long arg,struct file *filp)
{long err = -EINVAL;switch (cmd) { case F_GETFL:err = filp->f_flags;break;case F_SETFL:err = setfl(fd, filp, arg);break;
}static int setfl(int fd, struct file * filp, unsigned long arg)
{//arg = filp->f_flags | FASYNC//所以这句话(arg ^ filp->f_flags) & FASYNC 代表检查是否设置为FASYNC,是为真//filp->f_op->fasync 判断这个是否为真,即是否存在,如果存在就调用到底层fasyncif (((arg ^ filp->f_flags) & FASYNC) && filp->f_op->fasync) {error = filp->f_op->fasync(fd, filp, (arg & FASYNC) != 0);}}