異步通知的概念:
一旦設備就緒,主動通知應用程序。這樣應用程序根本不需要查詢設備狀態。
阻塞,非阻塞和異步:
-阻塞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);