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.heiqu.com/99a6d85c6ba91f562fd7b7d1d8adf324.html