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();
(没找到源码,且使用较少,暂时放弃分析)