Linux驱动开发--实现设备的异步通知

异步通知:即设备准备就绪时主动通知设备

基本实现原理:

    1,当设备可读时,发送一个信号通知应用程序

    2,应用程序接收到信号后,执行读操作

    举例:异步通知编程:

void input_handler(int num)
{
   char data[MAX_LEN];
   int len;
 //读取并输出STDIN_FILENO 上的输入
   len = read(STDIN_FILENO, &data, MAX_LEN);
   data[len] = 0;
   printf("input available:%s\n", data);
 }

 int main()
{
   int oflags;
 //启动信号驱动机制
   signal(SIGIO, input_handler);
   fcntl(STDIN_FILENO, F_SETOWN, getpid());
   oflags = fcntl(STDIN_FILENO, F_GETFL);
   fcntl(STDIN_FILENO, F_SETFL, oflags | FASYNC);
 //最后进入一个死循环,仅为保持进程不终止,如果程序中没有这个死循环
 //会立即执行完毕
   while (1);
 }
由此可见,为了在用户空间中能处理一个设备释放的信号,它必须完成以下3 项工作。
 通过F_SETOWN IO 控制命令设置设备文件的拥有者为本进程,这样从设备驱动发出的信号才能
被本进程接收到。
 通过F_SETFL IO 控制命令设置设备文件支持FASYNC,即异步通知模式。

 通过signal()函数连接信号和信号处理函数。


为了使设备支持异步通知机制,驱动程序中涉及以下3 项工作。
 支持F_SETOWN 命令,能在这个控制命令处理中设置filp->f_owner 为对应进程ID。不过此项工
作已由内核完成,设备驱动无须处理。
 支持F_SETFL 命令的处理,每当FASYNC 标志改变时,驱动程序中的fasync()函数将得以执行。
因此,驱动中应该实现fasync()函数。

 在设备资源可获得时,调用kill_fasync()函数激发相应的信号。



设备驱动中异步通知:

1,数据结构是fasync_struct 结构体;

2,两个函数分别如下:

    1  )处 理 FASYNC 标志变更的函数。

int fasync_helper(int fd, struct file *filp, int mode, struct fasync_struct **fa);

    2 )释 放信号用的函数。

void kill_fasync(struct fasync_struct **fa, int sig, int band);


基本编程模板

在设备结构体中加入fasync_struct 结构体指针
struct   xxx_dev{
struct  cdev  cdev;
...
struct  fasync_struct  * async_queue; /*异步结构体指针*/
};

在设备驱动的fasync()函数中,只需要简单地将该函数的3 个参数以及fasync_struct 结构体指针的指针作为第4 个参数传入fasync_helper()函数即可。
static  int xxx_fasync  (int fd, struct file *filp, int mode)
{
struct xxx_dev *dev = filp->private_data;
return fasync_helper(fd, filp, mode, &dev->async_queue);
}

在设备资源可以获得时,应该调用kill_fasync()释放SIGIO 信号,可读时第3 个参数设置为POLL_IN,可写时第3 个参数设置为POLL_OUT.
static   ssize_t xxx_write(struct file *filp, const char _ _user *buf, size_t count,loff_t *f_pos)
{
struct xxx_dev *dev = filp->private_data;
...
 /* 产生异步读信号 */
if (dev->async_queue)
kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
...
}

最后,在文件关闭时,即在设备驱动的release()函数中,应调用设备驱动的fasync()函数将文件从异步通知的列表中删除。
static   int xxx_release(struct inode *inode, struct file *filp)
{
struct xxx_dev *dev = filp->private_data;
/* 将文件从异步通知列表中删除 */
xxx_fasync(-1, filp, 0);
...
return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值