linux驱动之异步通知
2015-07-05 17:11
621 查看
异步通知
为了启动文件的异步通知机制,用户程序需要执行两个步骤:
1 fcntl(int fd, F_SETOWN, getpid()); //设置接受SIGIO和SIGURG的进程,如果getpid()为负表示以该值绝对值为值的进程组,其实就是对filp->f_owner赋值
signal(SIGIO, button_signal_function);//接收到SIGIO信号时,调用button_signal_function函数
2 flag |= FASYNC;
fcntl(fd, F_SETFL, flag);//设置文件状态标志,只有设置了FASYNC标志,才能启动异步通知,调用内核的fasync函数
驱动程序要使用的函数
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);
}
fasync_struct结构体如下
struct fasync_struct {
spinlock_t fa_lock;
int magic;
int fa_fd;
struct fasync_struct *fa_next; /* singly linked list */
struct file *fa_file;
struct rcu_head fa_rcu;
};
static int fasync_add_entry(int fd, struct file *filp, struct fasync_struct **fapp)
{
struct fasync_struct *new;
new = fasync_alloc();
if (!new)
return -ENOMEM;
/*
* fasync_insert_entry() returns the old (update) entry if
* it existed.
*
* So free the (unused) new entry and return 0 to let the
* caller know that we didn't add any new fasync entries.
*/
if (fasync_insert_entry(fd, filp, fapp, new)) {
fasync_free(new);
return 0;
}
return 1;
}
主要是调用fasync_insert_entry函数
struct fasync_struct *fasync_insert_entry(int fd, struct file *filp, struct fasync_struct **fapp, struct fasync_struct *new)
{
struct fasync_struct *fa, **fp;
spin_lock(&filp->f_lock);
spin_lock(&fasync_lock);
for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) {
if (fa->fa_file != filp)
continue;
spin_lock_irq(&fa->fa_lock);
fa->fa_fd = fd;
spin_unlock_irq(&fa->fa_lock);
goto out;
}
spin_lock_init(&new->fa_lock);
new->magic = FASYNC_MAGIC;
new->fa_file = filp;
new->fa_fd = fd;
new->fa_next = *fapp;
rcu_assign_pointer(*fapp, new);
filp->f_flags |= FASYNC;
out:
spin_unlock(&fasync_lock);
spin_unlock(&filp->f_lock);
return fa;
}
该函数在链表中查找是否存在指定的filp,如果存在将该fasync_struct对应的fa_fd替换成新的fd,如果不存在该filp,则添加新的fasync_struct结构体,并以指定的filp,fd等初始化,添加到链表的末尾。
当指定的事件发生时,内核使用kill_fasync函数通知应用程序
为了启动文件的异步通知机制,用户程序需要执行两个步骤:
1 fcntl(int fd, F_SETOWN, getpid()); //设置接受SIGIO和SIGURG的进程,如果getpid()为负表示以该值绝对值为值的进程组,其实就是对filp->f_owner赋值
signal(SIGIO, button_signal_function);//接收到SIGIO信号时,调用button_signal_function函数
2 flag |= FASYNC;
fcntl(fd, F_SETFL, flag);//设置文件状态标志,只有设置了FASYNC标志,才能启动异步通知,调用内核的fasync函数
驱动程序要使用的函数
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);
}
fasync_struct结构体如下
struct fasync_struct {
spinlock_t fa_lock;
int magic;
int fa_fd;
struct fasync_struct *fa_next; /* singly linked list */
struct file *fa_file;
struct rcu_head fa_rcu;
};
static int fasync_add_entry(int fd, struct file *filp, struct fasync_struct **fapp)
{
struct fasync_struct *new;
new = fasync_alloc();
if (!new)
return -ENOMEM;
/*
* fasync_insert_entry() returns the old (update) entry if
* it existed.
*
* So free the (unused) new entry and return 0 to let the
* caller know that we didn't add any new fasync entries.
*/
if (fasync_insert_entry(fd, filp, fapp, new)) {
fasync_free(new);
return 0;
}
return 1;
}
主要是调用fasync_insert_entry函数
struct fasync_struct *fasync_insert_entry(int fd, struct file *filp, struct fasync_struct **fapp, struct fasync_struct *new)
{
struct fasync_struct *fa, **fp;
spin_lock(&filp->f_lock);
spin_lock(&fasync_lock);
for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) {
if (fa->fa_file != filp)
continue;
spin_lock_irq(&fa->fa_lock);
fa->fa_fd = fd;
spin_unlock_irq(&fa->fa_lock);
goto out;
}
spin_lock_init(&new->fa_lock);
new->magic = FASYNC_MAGIC;
new->fa_file = filp;
new->fa_fd = fd;
new->fa_next = *fapp;
rcu_assign_pointer(*fapp, new);
filp->f_flags |= FASYNC;
out:
spin_unlock(&fasync_lock);
spin_unlock(&filp->f_lock);
return fa;
}
该函数在链表中查找是否存在指定的filp,如果存在将该fasync_struct对应的fa_fd替换成新的fd,如果不存在该filp,则添加新的fasync_struct结构体,并以指定的filp,fd等初始化,添加到链表的末尾。
当指定的事件发生时,内核使用kill_fasync函数通知应用程序
相关文章推荐
- 基于u盘安装centos6.0
- 【零基础】CentOS 7 64位系统下编译Hadoop2.7.0
- Linux/Unix下的任务管理器-top命令
- Linux下获取块设备大小
- Linux系统用到命令积累
- 利用Unix/Linux的IPC机制仿真一个音乐厅门票订售系统
- CentOS6.x 升级 CentOS7.1
- linux块设备驱动之相关结构体
- Linux 基础命令知识1
- centos 扩展root根分区的大小
- linux下安装mysql
- ubuntu常用文件搜索命令 分类: linux 学习笔记 ubuntu 2015-07-05 15:40 84人阅读 评论(0) 收藏
- 《鸟哥的Linux私房菜》第五章 首次登录与在线求助man page
- Linux C single linked for any data type
- Linux C socket 封装
- kali linux虚拟wifi搭建
- linux下查看已经安装的jdk 并卸载jdk
- linux查看java jdk安装路径和设置环境变量
- Linux磁盘使用
- LINUX下JBOSS的安装及配置