Linux设备驱动中的异步通知
异步通知的概念:
一旦设备就绪,主动通知应用程序。这样应用程序根本不需要查询设备状态。
阻塞,非阻塞和异步:
- 阻塞 IO 是等待设备可访问后再访问
- 非阻塞 IO 是查询设备是否可以访问
- 异步通知是设备通知自身可以访问
为了使支持异步通知机制,驱动程序应该涉及以下 3 项工作。
支持 F_SETOWN 命令,能在这个控制命令处理。
处理 FASYNC 标志更变的函数
Int fasync_helper(int fd, struct file*filp, int mode, struct fasync_struct **fa);
释放信号用的函数
Void kill_fasync(struct fasync_struct **fa,int sig, int band);
void kill_fasync(struct fasync_struct **fp,int sig, int band)
{
/*First a quick test without locking: usually
* the list is empty.
*/
if(*fp) {
read_lock(&fasync_lock);
/*reread *fp after obtaining the lock */
__kill_fasync(*fp,sig, band);
read_unlock(&fasync_lock);
}
}
void __kill_fasync(struct fasync_struct*fa, int sig, int band)
{
while(fa) {
structfown_struct * fown;
if(fa->magic != FASYNC_MAGIC) {
printk(KERN_ERR"kill_fasync: bad magic number in "
"fasync_struct!\n");
return;
}
fown= &fa->fa_file->f_owner;
/*Don't send SIGURG to processes which have not set a
queued signum: SIGURG has its own defaultsignalling
mechanism. */
if(!(sig == SIGURG && fown->signum == 0))
send_sigio(fown,fa->fa_fd, band);
fa= fa->fa_next;
}
}
void send_sigio(struct fown_struct *fown,int fd, int band)
{
structtask_struct *p;
enumpid_type type;
structpid *pid;
intgroup = 1;
read_lock(&fown->lock);
type= fown->pid_type;
if(type == PIDTYPE_MAX) {
group= 0;
type= PIDTYPE_PID;
}
pid= fown->pid;
if(!pid)
gotoout_unlock_fown;
read_lock(&tasklist_lock);
do_each_pid_task(pid, type, p) {
send_sigio_to_task(p,fown, fd, band, group);
} while_each_pid_task(pid, type, p);
read_unlock(&tasklist_lock);
out_unlock_fown:
read_unlock(&fown->lock);
}
通过内核,给所有的进程发送信号。
用户对应进程可以接受该信号,并作处理。
用户进程要做的是:
1. 绑定信号和信号处理函数
Signal(SIGIO,input_handler)
2. 设定本进程为某个标准输入文件的拥有者。这样内核就知道信号发送给那个进程。
Fcntl(STDIN_FILENO,F_SETNO,getpid());
3. 对输入文件设定异步标志位。
Fcntl(STDIN_FILENO,F_SETFL,oflags | FASYNC) ;
本文转载自推酷网,原文链接:http://www.tuicool.com/articles/6Z3aQj