技术标签: linux 异步通知 Linux Kernel fasync
linux 系统中的 fasync 类似于 qt 的信号与槽机制,在应用程序向驱动程序请求数据时可以使用这种方法。驱动程序中有数据可读,发送信号给应用程序来读取。用法非常简单,大概的流程如下:
1、应用程序中注册信号处理函数
signal(SIGIO, my_signal_fun);6、应用程序收到信号,信号处理函数被调用
驱动程序:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/irq.h>
#include <asm/uaccess.h>
#include <mach/gpio-fns.h> //s3c2410_gpio_getpin
#include <mach/gpio-nrs.h> //S3C2410_GPG(x)
#include <linux/poll.h>
MODULE_LICENSE("GPL");
//中断触发方式的 一些宏定义
#define __IRQT_FALEDGE IRQ_TYPE_EDGE_FALLING
#define __IRQT_RISEDGE IRQ_TYPE_EDGE_RISING
#define __IRQT_LOWLVL IRQ_TYPE_LEVEL_LOW
#define __IRQT_HIGHLVL IRQ_TYPE_LEVEL_HIGH
#define IRQT_NOEDGE (0)
#define IRQT_RISING (__IRQT_RISEDGE)
#define IRQT_FALLING (__IRQT_FALEDGE)
#define IRQT_BOTHEDGE (__IRQT_RISEDGE|__IRQT_FALEDGE)
#define IRQT_LOW (__IRQT_LOWLVL)
#define IRQT_HIGH (__IRQT_HIGHLVL)
#define IRQT_PROBE IRQ_TYPE_PROBE
static struct class *fasyncdrv_class;
static struct device *fasyncdrv_class_dev;
static unsigned char key_val = 0x22; //保存键值
int major; //主设备号
static struct fasync_struct *button_async; //存放信号接受者的进程ID等信息
/***************************************************************************************
* 结构名称:keys_desc
* 主要功能:描述 按键 寄存器地址、按下键值、弹起键值
* 备 注:
****************************************************************************************/
struct keys_desc{
unsigned int key_addr;
unsigned char key_value_down;
unsigned char key_value_up;
};
/***************************************************************************************
* 数组名称:keys_desc
* 数组类型:struct keys_desc
* 备 注:mini2440开发板6个按键描述数组
****************************************************************************************/
struct keys_desc keys_desc[6]={
{S3C2410_GPG(0) ,0x01 ,0x81},
{S3C2410_GPG(3) ,0x02 ,0x82},
{S3C2410_GPG(5) ,0x03 ,0x83},
{S3C2410_GPG(6) ,0x04 ,0x84},
{S3C2410_GPG(7) ,0x05 ,0x85},
{S3C2410_GPG(11) ,0x06 ,0x86},
};
/***************************************************************************************
* 函数名称:buttons_irq
* 主要功能:处理对应于各个中断号的中断
* 备 注:根据中断号irq以及dev_id区分不同中断
****************************************************************************************/
static irqreturn_t buttons_irq(int irq, void *dev_id)
{
struct keys_desc * keys_desc = (struct keys_desc *)dev_id;
unsigned int keyval;
keyval = s3c2410_gpio_getpin(keys_desc->key_addr);
if (keyval)
{
/* 松开 */
key_val = keys_desc->key_value_up;
}
else
{
/* 按下 */
key_val = keys_desc->key_value_down;
}
//发送信号给应用程序 数据可读
kill_fasync (&button_async, SIGIO, POLL_IN);
return IRQ_RETVAL(IRQ_HANDLED);
}
/***************************************************************************************
* 函数名称:fasync_drv_open
* 主要功能:向内核传递中断信息,中断号、中断处理函数、触发方式、名称、dev_id
* 备 注:驱动程序设备节点打开时自动运行
****************************************************************************************/
static int fasync_drv_open(struct inode *inode, struct file *file)
{
//int request_irq(unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char *devname, void *dev_id)
request_irq(IRQ_EINT8, buttons_irq, IRQT_BOTHEDGE, "S1", &keys_desc[0]);
request_irq(IRQ_EINT11, buttons_irq, IRQT_BOTHEDGE, "S2", &keys_desc[1]);
request_irq(IRQ_EINT13, buttons_irq, IRQT_BOTHEDGE, "S3", &keys_desc[2]);
request_irq(IRQ_EINT14, buttons_irq, IRQT_BOTHEDGE, "S4", &keys_desc[3]);
request_irq(IRQ_EINT15, buttons_irq, IRQT_BOTHEDGE, "S5", &keys_desc[4]);
request_irq(IRQ_EINT19, buttons_irq, IRQT_BOTHEDGE, "S6", &keys_desc[5]);
return 0;
}
/***************************************************************************************
* 函数名称:fasync_drv_close
* 主要功能:告诉内核 屏蔽这些中断,删除中断处理函数
* 备 注:关闭设备节点时自动运行
****************************************************************************************/
int fasync_drv_close(struct inode *inode, struct file *file){
free_irq(IRQ_EINT8, &keys_desc[0]);
free_irq(IRQ_EINT11, &keys_desc[1]);
free_irq(IRQ_EINT13, &keys_desc[2]);
free_irq(IRQ_EINT14, &keys_desc[3]);
free_irq(IRQ_EINT15, &keys_desc[4]);
free_irq(IRQ_EINT19, &keys_desc[5]);
return 0;
}
/***************************************************************************************
* 函数名称:fasync_drv_read
* 主要功能:应用层调用read函数获取数据
* 备 注:
****************************************************************************************/
static ssize_t fasync_drv_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
{
/* 如果有按键动作, 返回键值 */
copy_to_user(buf, &key_val, 1);
return 0;
}
/***************************************************************************************
* 函数名称:fifth_drv_fasync
* 主要功能:调用fasync_helper初始化fasync_struct结构体,主要是应用程序的PID等信息
* 备 注:上层应用调用fcntl改变设备文件flag都会调用.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);
}
/***************************************************************************************
* 结构名称:fasync_drv_fops
* 结构类型:file_operations
* 备 注:每一个设备号对应一个file_operations类型的结构,存放该驱动程序的各种操作函数
****************************************************************************************/
static struct file_operations fasync_drv_fops = {
.owner = THIS_MODULE,
.open = fasync_drv_open,
.read = fasync_drv_read,
.release = fasync_drv_close,
.fasync = fifth_drv_fasync,
};
/***************************************************************************************
* 函数名称:fasync_drv_init
* 主要功能:获取主设备号、注册设备类、创建设备节点
* 备 注:加载驱动程序时自动运行
****************************************************************************************/
static int __init fasync_drv_init(void){
printk(KERN_ALERT "init OK\n");
major = register_chrdev(0, "fasync_drv", &fasync_drv_fops);
fasyncdrv_class = class_create(THIS_MODULE, "fasyncdrv");
fasyncdrv_class_dev = device_create(fasyncdrv_class, NULL, MKDEV(major, 0), NULL, "button"); /* /dev/button */
return 0;
}
/***************************************************************************************
* 函数名称:fasync_drv_exit
* 主要功能:注销设备(释放设备号)、注销设备类、销毁设备节点
* 备 注:卸载驱动程序时自动运行
****************************************************************************************/
static void __exit fasync_drv_exit(void){
printk(KERN_ALERT "exit OK\n");
unregister_chrdev(major, "fasync_drv"); //取消注册
device_unregister(fasyncdrv_class_dev); //取消设备节点
class_destroy(fasyncdrv_class); //销毁类
}
module_init(fasync_drv_init);
module_exit(fasync_drv_exit);
应用程序:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <poll.h>
#include <signal.h>
int fd;
void my_signal_fun(int signum)
{
unsigned char key_val;
read(fd, &key_val, 1);
printf("key_val: 0x%x\n", key_val);
}
int main(int argc, char **argv)
{
int ret;
int Oflags;
fd = open("/dev/button", O_RDWR);
signal(SIGIO, my_signal_fun);
if (fd < 0)
{
printf("can't open!\n");
}
fcntl(fd, F_SETOWN, getpid());
Oflags = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, Oflags | FASYNC);//设置设备程序支持异步通知
while (1)
{
sleep(1000);
}
return 0;
}
这篇文章是sql语句的答案篇,数据库表信息请查看上一篇 “mysql 多表查询练习题(一)数据准备”1.查询平均成绩大于70分的同学的学号和平均成绩select sid,avg(score) avg_sc from sc group by sid having avg_sc>702.查询所有同学的学号、姓名、选课数、总成绩select sc.sid,st.snam...
ADSL拨号在F19中我没有找到拨号的图形操作,于是只好用命令来完全# 找到你的拨号网卡名ifconfig #这里的名字可能是eth0, em1, p2p1之类的# 开始设置拨号信息sudo pppoe-setup# Enter your login name (default root): 这里填ADSL帐号# (default eth0): 这里填从ifconfig得到的网卡名#
bzoj 4811 由乃的OJ考虑树链剖分.树剖后用一颗线段树维护一段连续区间,类似于一个函数,各位上进入 \(0/1\) ,输出的数字分别是什么.注意到最多只有 \(64\) 位,可以用一个 \(unsigned\ long\ long\) 的大数状压表示,合并两段区间时推导一下可以做到 \(O(1)\) .注意 \(3 种\)位运算混在一起,满足交换律,却不满足结合律,所以从区间左/右...
CStatic m_loginstainfo;编程环境:VS2013,MFC如何实现静态文本框的刷新显示文字修改静态文本框的ID,这里改成了IDC_STAINFO方法一GetDlgItem(IDC_STAINFO)->ShowWindow(SW_HIDE);GetDlgItem(IDC_STAINFO)->SetWindowText(_T("登录成功!"));Ge...
之前对*和&符号一直理解的比较浅显。只知道: *p好像表示的是一个指针; &p表示的是一个地址。 然而这次当遇到了下面这个情况的时候: int a = 10; int *b = &a;printf(“%d\n”, a); printf(“%d\n”, &a); printf(“%d\n”, b); printf(“%d\n”, *b);结果: 10 6487620 648762
对于现代语言而言,包管理器基本上是标配。Java有Maven,Python有pip,Ruby有gem,Nodejs有npm。PHP的则是PEAR,不过PEAR坑不少:依赖处理容易出问题配置非常复杂难用的命令行接口好在我们有Composer,PHP依赖管理的利器。它是开源的,使用起来也很简单,提交自己的包也很容易。安装ComposerComposer需要PHP 5.3.2+才能运行。$ curl -...
HTML结构4种loading预加载动画的HTML结构分别如下:CSS样式然后分别为它们添加下面的CSS样式。/* KEYFRAMES */@keyframes spin {from {transform: rotate(0);}to{transform: rotate(359deg);}}@keyframes configure-clockwise {0% {transform: rotate(...
大概原因就是,装的pytorch版本太老或者没装好,得利用官网的命令重新装一次进入https://pytorch.org/get-started/previous-versions/找到conda安装下的你的系统(windows)和CUDA版本对应的命令,复制下来。把后面的 -c pytorch 去掉不过,在运行这个命令前,你最好先给conda添加国内镜像源。conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anac
在android开发过程中,屏幕适配是一件非常重要的工作,主要原则有以下几点对于控件而言,尽量不要使用固定的宽度和高度,但推荐使用固定的外边距局和内边距。对于drawable-xxx而言,没必要每个dpi都放置图片,完全可以再drawable-hdpi中放入720px级别的图片就可以完成适配,此外,如果某些部位确实需要调整的话,可以结合values-xxxx。 对于平滑色彩,渐变色彩,点击按压效果...
题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=201////////////////////////////////////////////////////////此题的意思为找到严格递增或者严格递减的子序列的最长长度;由于x的值各不相同,所以可以按照x排序;然后对y求最长递增子序列和最长递减子序列,去两者较大的输出
靶机网址:https://www.vulnhub.com/entry/ha-narak,569/目录一、信息搜集:二、漏洞利用与探测:三、提权一、信息搜集:获取IP:nmap -sP 192.168.8.0/24 端口扫描:nmap -sV -p- -sC 192.168.8.132 -n -vv22、80端口均开启访问192.168.8.132从页面搜索信息·翻译了一下网页内容信息提取关键字或许有用: yamdoot,...
求和相关使用求和函数sum([axis=0|1]),根据参数不同可实现不同求和方式。矩阵整体数据的求和运算使用无参求和函数,可实现对矩阵整体数据的求和运算。from numpy import matsample = mat([[1, 2], [3, 4]]sample.sum()执行结果:101010矩阵按列求和运算求和函数参数为0时,可实现矩阵按列求和运算。from num...