linux驱动编程--异步通知与异步I/O

        In a general way, there are two methods for process control: synchronization and asynchronization.

        synchronization  is involves block(阻塞) , no-block(轮询) ( poll ). it just like anti-asynchronization.

        asynchronization is include signal(信号) and asynchronization I/O( 异步I/O). the kernel is do as they arrived.(随到随做). 信号和异步通知的有一些实现上的不同。

                信号的逻辑模型是:进程做自己的事->信号来了,跳过去执行信号处理函数->跳回来继续执行;

                异步I/O的逻辑模型是:进程做自己的事->抛出一个I/O请求->继续做自己的事->要用到数据了,再去查询别人是不是已经把I/O请求->继续做事

 

Asynchronous  notification (异步通知)

        @signal for software is equal to @interrupt for hardware.(信号是软件上对于中断的模拟)

        service mode is based on the fellowing theory: one signal is corressponds to a slot-function. just like the interrupt do.(相当于中断)

 //应用层
 fcntl( STDIN_FILENO, F_SETOWN, getpid());   //设置文件的拥有者。在驱动发送的信号会传输给拥有者
 oflag = fcntl( STDIN_FILENO, FGETFL);  
 fcntl( STDIN_FILENO, FSETFL, oflag|FASYNC); //设置异步通知
 signal( SIGIO, handler);                    //设置信号处理函数,一个萝卜一个坑
 //驱动层
 fasync_helper(int fd,struct file * filp,int on,struct fasync_struct * * fapp);
 kill_fasync(struct fasync_struct * * fp,int sig,int band);
    

        the most important thing is what @fasync_helper() and @kill_saync() do. @fasync_helper() will add those information, from upper layer, to a list. @kill_fasync() will check the list and send signal. The fellowing is the reason that i suppose.

/*
 * fasync_helper() is used by almost all character device drivers
 * to set up the fasync queue. It returns negative on error, 0 if it did
 * no changes and positive if it added/deleted the entry.
 */
int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp)
{
	struct fasync_struct *fa, **fp;
	struct fasync_struct *new = NULL;
	int result = 0;

	if (on) {
		new = kmem_cache_alloc(fasync_cache, GFP_KERNEL);
		if (!new)
			return -ENOMEM;
	}

	/*
	 * We need to take f_lock first since it's not an IRQ-safe
	 * lock.
	 */
	spin_lock(&filp->f_lock);
	write_lock_irq(&fasync_lock);
	for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) {	//检查异步链表是否该文件对应的信息已经存在
		if (fa->fa_file == filp) {//假如该file已经被添加过了
			if(on) {
				fa->fa_fd = fd;
				kmem_cache_free(fasync_cache, new);
			} else {
				*fp = fa->fa_next;
				kmem_cache_free(fasync_cache, fa);
				result = 1;
			}
			goto out;
		}
	}
	//假如不存在就添加进去
	if (on) {
		new->magic = FASYNC_MAGIC;
		new->fa_file = filp;
		new->fa_fd = fd;
		new->fa_next = *fapp;
		*fapp = new;
		result = 1;
	}
out:
	if (on)
		filp->f_flags |= FASYNC;
	else
		filp->f_flags &= ~FASYNC;
	write_unlock_irq(&fasync_lock);
	spin_unlock(&filp->f_lock);
	return result;
}

        the blue code is try to add information to the list. the next one is @kill_fasync().

	kill_fasync(struct fasync_struct * * fp,int sig,int band);
		/*
			fp	--异步对象链表
			sig	--通知的信号类型
			band--POLL_IN, POLL_OUT
		*/
	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) {	//会通知所有的注册进程
			struct fown_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;		//找到文件拥有者的进程ID
			/* Don't send SIGURG to processes which have not set a
			   queued signum: SIGURG has its own default signalling
			   mechanism. */
			if (!(sig == SIGURG && fown->signum == 0))
				send_sigio(fown, fa->fa_fd, band);	//fa_fd为文件描述符
			fa = fa->fa_next;
		}
	}

        check those blue code, it is sending signal to some process.
Asynchronous I/O (异步I/O)

         //添加I/O请求
         aio_read();
         aio_write();
         //I/O请求执行结果
         aio_error(); //查询
         aio_return(); //获取
         aio_suspend();//阻塞直到请求完成
         aio_cancel();
         //批量管理I/O请求
         lio_listio();
        (没找到源码,且使用较少,暂时放弃分析)

 


 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值