linux驱动学习笔记 异步通知

前言

正在根据韦东山老师的视频和代码来学习写linux驱动,记录笔记在这里,方便复习与查阅

概述

异步通知机制能让驱动主动通知应用程序做某些事,而不需要应用程序不断查询驱动的状态来决定做什么事

如果想要要实现异步通知的功能

驱动程序需要做的事有:
  • 新建一个信号并注册它
  • 发送信号通知应用程序
应用程序需要做的事有:
  • 收到信号后需要执行的函数
  • 把这个函数与驱动程序的信号关联起来

疑问

  • 应用程序的进程ID是不固定的,驱动如何知道要发送信号给谁?

解答疑问

  • 应用程序需要执行某个函数调用驱动的fasync_helper函数
  • fasync_helper会关联 应用程序进程 与 驱动程序的信号
  • 之后,应用程序执行kill_fasync就能向应用程序进程发送信号
  • 应用程序进程会根据信号类型,来执行对应注册的函数

参考资料http://blog.chinaunix.net/uid-20498191-id-1704861.html

知识点扩展

  • kill_fasync 、fasync_helper
  • signal、SIGIO
  • fcntl
  • getpid()
signal、SIGIO
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);

这个博文写的非常好,可以看一看:
https://blog.csdn.net/weibo1230123/article/details/81505152

getpid()

获取当前pid

fcntl

fcntl函数的作用是改变已打开的文件性质
在这里插入图片描述
参考资料:https://www.cnblogs.com/zxc2man/p/7649240.html

个人理解下面几行代码可以 :
1、关联当前信号与进程ID
2、 给文件增加异步通知的文件状态标识
fcntl(fd, F_SETOWN, getpid());
Oflags = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, Oflags | FASYNC);

fasync_helper

哪个进程调用了fasync_helper,kill_fasync就向哪个进程发信号
int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp)

kill_fasync用法

button_async通过fasync_helper关联到了应用程序上,kill_fasync根据这个就知道向谁发送数据了
kill_fasync (&button_async, SIGIO, POLL_IN);

贴上相关代码

在驱动程序中

//定义一个fasync_struct 类
static struct fasync_struct *button_async;

//调用这个函数发送信号通知应用程序
kill_fasync (&button_async, SIGIO, POLL_IN);

//fasync_helper作用就是初始化fasync,包括分配内存和设置属性
static int fifth_drv_fasync (int fd, struct file *filp, int on)
{
	printk("driver: fifth_drv_fasync\n");
	return fasync_helper (fd, filp, on, &button_async);
}

//通过file_operations 关联fifth_drv_fasync函数
static struct file_operations sencod_drv_fops = {
    .owner   =  THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
    .open    =  fifth_drv_open,     
	.read	 =	fifth_drv_read,	   
	.release =  fifth_drv_close,
	.poll    =  fifth_drv_poll,
	.fasync	 =  fifth_drv_fasync,
};

在应用程序中

void my_signal_fun(int signum)
{
	unsigned char key_val;
	read(fd, &key_val, 1);
	printf("key_val: 0x%x\n", key_val);
}


signal(SIGIO, my_signal_fun);
fd = open("/dev/buttons", O_RDWR);
if (fd < 0)
{
	printf("can't open!\n");
}

fcntl(fd, F_SETOWN, getpid());

Oflags = fcntl(fd, F_GETFL); 

fcntl(fd, F_SETFL, Oflags | FASYNC);

猜你喜欢

转载自blog.csdn.net/tiantangmoke/article/details/103191436