标签:linux驱动
异步通知:
用户程序需完成两个步骤:
1、指定属主进程owner
使用fcntl系统调用的F_SETOWN,属主进程的进程ID就被保存在filp->f_owner中 2、真正启用异步通知机制
在设备中设置FASYNC标志,通过fcntl的F_SETFL
执行完这两个步骤后,输入文件就可以在新数据到达时请求发送一个SIGIO信号,该信号发送到filp->f_owner中保存的进程(负值为进程组)
不是所有设备都支持异步通知,我们也可以选择不提供异步通知功能,应用程序通常假设只有套接字和终端才有异步通知能力。当多于一个文件可以异步通知时,进程收到信号仍然必须借助poll或select来确定输入的来源。
驱动程序中的实现:
1、F_SETOWN被调用时对filp->f_owner赋值,此外什么也不做
2、在执行F_SETFL启用FASYNC时,调用驱动程序的fasync方法,只要file->f_flags中的FASYNC标志发生变化,就会调用该方法,以便把这个变化通知驱动程序,使其能正确响应。文件打开时,FASYNC标志会被默认为是清除的。
3、当数据到达时,所有注册为异步通知的进程都会被发送一个SIGIO信号。
设备数据结构中应该有异步通知列表,以下函数添加列表:
int fasync_helper(int fd, struct file *filp, int mode, struct fasync_struct **fa);
和wait_queue的实现差不多,使用以下函数在数据到来时通知异步列表中文件的属主进程:
int kill_fasync(struct fasync_struct **fa, int sig, int band);
文件关闭时需从异步通知列表中删除filp
定位设备:
llseek实现:
如果不实现llseek方法,内核默认修改filp->f_pos来执行定位。
某些设备是不能定位的,例如串口和键盘,应该在open方法中调用onseekable_open,以便通知内核设备不支持llseek:
int nonseekable_open(struct inode* inode, struct file *filp);
上述调用会把给定的filp标记为不可定位,lseek和pread、pwrite的调用会失败。
本文出自 “重剑无锋” 博客,请务必保留此出处http://qianyang.blog.51cto.com/7130735/1620575
标签:linux驱动
原文地址:http://qianyang.blog.51cto.com/7130735/1620575