驱动开发之始,(五)异步通知

情形分析:一个进程需要从外设读取采集到的数据进行处理,如果有新的数据到来,应用程序可以周期性地调用poll来检查数据,但是这样做的效率并不高。因此,通过使用异步通知,应用程序可以在数据可用时收到一个信号,转而进行处理,而不需要不停的使用查询的方式来检查有无新数据的到来。

为了启用文件的异步通知机制,应用程序执行以下三个步骤:

step1:指定一个进程作为文件的“属主(owner)”(在file结构中讲到)。当进程使用fcntl系统调用执行F_SETOWN命令时,属主进程的进程ID号就被保持在filp->f_owner中,目的是为了让内核知道应该通知哪个进程。

step2:应用程序还必须在设备中设置FASYNC标志,通过使用fcntl的F_SETFL命令。

step3:输入文件就可以在新数据到达时请求发送一个SIGIO信号。该信号被发送到存放在flip->f_owner中的进程。

signal(SIGIO, &input_handler);
fcntl(STDIN_FILENO, F_SETOWN, getpid());
oflags = fcntl(STDIN_FILENO, F_GETFL);
fcntl(STDIN_FILENO, F_SETFL, oflags | FASYNC);

从驱动程序的角度考虑

1.F_SETOWN被调用时对filp->f_owner赋值

2.执行F_SETFL启动FASYNC时,调用驱动程序的fasync方法。只要filp->f_flags中的FASYNC标志发生了变化,就会调用该方法。在文件打开时,FASYNC标志默认是清除的。

3.当数据到达时,所有注册为异步通知的进程都会被发送一个SIGIO信号。

异步通知执行的通用方法涉及一个结构体和两个函数,在<linux/fs.h>文件中,结构体声明为struct fasync_struct。和等待队列的方式类似,需要把一个该类型的指针插入设备特定的数据结构中。驱动程序需要调用的两个函数

对于大多数字符设备驱动建立异步队列调用该函数,当一个打开的文件的FASYNC标志被修改时,调用fasync_helper从相关的进程列表中增加或删除文件

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);
}

如果没有无改变返回0,添加或删除成功返回正数,错误时返回负数。

void kill_fasync(struct fasync_struct **fp, int sig, int band)
{
        /* First a quick test without locking: usually
	 * the list is empty.
	 */
	if (*fp) {
		rcu_read_lock();
		kill_fasync_rcu(rcu_dereference(*fp), sig, band);
		rcu_read_unlock();
	}
}

当数据到达时,可使用kill_fasync通知所有的相关进程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值