linux驱动学习笔记 异步通知

10 阅读 作者:tiantangmoke 2020-03-09

前言

正在根据韦东山老师的视频和代码来学习写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);
原文地址:https://blog.csdn.net/tiantangmoke/article/details/103191436
热门教程
Linux数据删除与恢复那些事儿2-video 0
linux嵌入式开发+驱动开发 0
嵌入式LINUX网络编程应用开发班UDP网络程序设计共享内存通讯GDB程序调试 0
Linux高级架构师12期VIP综合视频 0
linux嵌入式开发+驱动开发教程 内核启动过程和内核核心结构 ARM体系结构和汇编 0
linux系统目录结构知识讲解 0
linux系统定时任务crond入门讲解 0
linux磁盘读写的工作原理细节磁道-柱面-扇区知识总结磁盘容量计算公式原理 0
Centos6.5linux系统优化初步讲解 0
linux系统文件属性inode与block知识9条总结 0
linux系统磁盘分区知识深入讲解 0
linux基础正则表达式手把手实战讲解 0
linux文件系统ext2内部知识讲解ext2文件系统删除原理 0
linux系统文件权限体系实战深入讲解suid和sgid 0
企业项目案例1-linux用户权限集中管理方案 0
linux系统文件权限体系实战讲解 0
企业级生产场景全网备份与集群架构解决方案 0
linux系统网络基础及故障排查大总结 0
SHELL脚本企业级案例sshkey架构批量分发文件expect非交互式批量分发密钥 0
python linux系统编程GIL的问题异步的实现 0
相关文章
JavaScript学习笔记:迷宫游戏 16
windows mysql 学习笔记 第十天(基础习题) 16
《SQL必知必会》学习笔记(sqlite) 16
SpringBoot学习笔记三、http接口请求 16
Netty学习笔记(9)——Netty组件ByteBuf 16
MLX90640开发笔记(一)概述及开发资料准备 16
numpy基础语法学习笔记 16
笔记--STM32F407调试BQ4050--SMBUS通信 16
英语学习笔记2019-12-06 16
Flink菜鸟入坑笔记 16
linux-day2 16
Java并发编程实战&mdash;&mdash;学习笔记(一) 16
解决linux tomcat 内存溢出 16
linux系列之常用运维命令整理笔录 16
linux 学习笔记 第三天 16
关于字,字节,位数的问题笔记总结 16
docker学习笔记:docker-compose 16
linux或windows环境下pytorch的安装与检查验证(解决runtimeerror问题) 16
前端技术之:如何在vuex状态管理action异步调用结束后执行UI中的方法 16
微机原理学习笔记 16