标签:gis fun turn 交互 sig timer == 模式 接收
通常应用程序跟驱动之间交互,主要是通过轮询的方式。这种方式效率非常低下。
下面介绍一种异步通知的方式。在这种模式下,应用程序不需要查询驱动,当驱动需要应用程序读取数据时,发送一个信号给应用程序,应用程序收到信号后,再去从驱动读取数据。
驱动代码:
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/moduleparam.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/poll.h>
#include <linux/fcntl.h>
#include <linux/signal.h> //for SIGIO,POLL_IN
#include <linux/timer.h>
#include <linux/jiffies.h>
//设备名
#define DEVICE_NAME "sync"
//主设备号
#define DEVICE_MAJOR 228
//异步通知结构变量
struct fasync_struct *async_queue;
//内核定时器
struct timer_list my_timer;
//定时器超时函数
static void timer_function(unsigned long arg)
{
//发送信号到用户空间,POLL_IN表示可写
kill_fasync(&async_queue, SIGIO, POLL_IN);
}
//用户空间调用fcntl函数时会调用这个函数
static int async_fasync(int fd, struct file *filp, int mode)
{
//根据用户空间的需要,获取或设置相应的属性
return fasync_helper(fd, filp, mode, &async_queue);
}
static int async_open(struct inode *node,struct file *flip)
{
//初始化定时器
init_timer(&my_timer);
my_timer.data = 0;
//定时器超时函数
my_timer.function = &timer_function;
//定时器超时时间(当前时间的后1000个时钟滴答)
my_timer.expires = jiffies + 5*200;
//启动定时器
add_timer(&my_timer);
return 0;
}
static struct file_operations async_fops =
{
.owner = THIS_MODULE,
.fasync = async_fasync,
.open = async_open,
};
static int __init dev_init(void)
{
int ret;
//注册字符设备
ret = register_chrdev(DEVICE_MAJOR , DEVICE_NAME, &async_fops);
if (ret < 0)
{
printk(DEVICE_NAME " can‘t register\n");
return ret;
}
else
{
printk(DEVICE_NAME " register successful\n");
return 0;
}
}
static void __exit dev_exit(void)
{
//撤销字符设备
unregister_chrdev(DEVICE_MAJOR , DEVICE_NAME);
printk("unregister success \n");
}
module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("LKN@SCUT");
编译成功后会生成fasync.ko文件,先加载该驱动:
#insmod fasync.ko
然后,在/dev目录下创建设备文件:
#mknod sync c 228 1
接着,编写应用程序:
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
//是否已接收到信号标志
int flag = 0;
//信号处理函数定义,由内核调用执行
void sig_handler(int signo)
{
if (signo==SIGIO)
{
printf("receive successful!!!\n");
flag = 1;
}
}
int main()
{
struct sigaction action;
int async_fd;
memset(&action, 0, sizeof(action));
//信号处理函数
action.sa_handler = sig_handler;
action.sa_flags = 0;
//注册信号类型
sigaction(SIGIO, &action, NULL);
async_fd = open("/dev/sync", O_RDONLY);
if(async_fd < 0)
{
printf("can not open /dev/sync \n");
return -1;
}
//告诉驱动当前进程的PID
fcntl(async_fd, F_SETOWN, getpid());
//设置驱动的FASYNC属性,支持异步通知
fcntl(async_fd, F_SETFL, fcntl(async_fd, F_GETFL) | FASYNC);
printf("waiting for receive...\n");
while(!flag)
{
}
close(async_fd);
return 0;
}
标签:gis fun turn 交互 sig timer == 模式 接收
原文地址:https://www.cnblogs.com/utopia007/p/12577256.html