kill_fasync及fasync_helper用于异步通知中
kill_fasync(&fasync_read, SIGIO, POLL_IN);; //向用户发可读信号,fasync_read可用来区分向谁发
哪个进程调用这个fasync_helper就向谁发
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;
}
write_lock_irq(&fasync_lock);
for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) {
if (fa->fa_file == filp) {
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:
write_unlock_irq(&fasync_lock);
return result;
}
别忘了realease时调用一把释放
所以用法为
用户层
signal(SIGIO, input_handler); //让input_handler()处理SIGIO信号
fcntl(fd, F_SETOWN, getpid());
oflags = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, oflags | FASYNC); //调用驱动的
fasync_helper
驱动
kill_fasync发送信号调用signal安装的信号
设备关闭时 kpp_fasync(-1, filp, 0);
代码示例(字符设备驱动案例)
(驱动部分)
struct fasync_struct *fasync_read;
static int read_fasync(int fd, struct file *filp, int mode)
{
return fasync_helper(fd, filp, mode, &fasync_read);
}
static const struct file_operations my_gpio_fops =
{
.owner = THIS_MODULE,
.open = my_gpio_open,
.release = my_gpio_release,
.read = my_gpio_read,
.unlocked_ioctl = my_gpio_ioctl,
.fasync = read_fasync,
};
static irqreturn_t my_handler_u0(int irq, void *dev_id)//驱动中中断处理函数
{
......
if (fasync_read){
kill_fasync(&fasync_read, SIGIO, POLL_IN);//异步通知用户层
}
}
用户层
signal(SIGIO, input_handler);
fcntl(gps_fd, F_SETOWN, getpid());
oflags = fcntl(gps_fd, F_GETFL);
fcntl(gps_fd, F_SETFL, oflags | FASYNC);
void input_handler(int signum)//用户层响应底层信号的处理
{
........
}