#include <linux/module.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/poll.h>
#include <linux/sched.h>
#include <linux/sched/signal.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/list.h>
#include <linux/moduleparam.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/uio.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <asm/unaligned.h>
#include <linux/fs.h>
#include <linux/compat.h>
#include <linux/blkdev.h>
#include <linux/mutex.h>
#include <linux/poll.h>
#include <linux/vmalloc.h>
#define MEM_CLEAR 0x1
#define GLOBALFIFO_MAJOR 230
#define GLOBALFIFO_SIZE 0x1000
static struct fasync_struct *megasas_async_queue;
static int globalfifo_major = GLOBALFIFO_MAJOR;
module_param(globalfifo_major, int, S_IRUGO);
/* 设备结构体 */
struct globalfifo_dev {
struct cdev cdev;
unsigned int current_len; /* 当前FIFO中有效数据的长度 */
unsigned char mem[GLOBALFIFO_SIZE];
};
struct globalfifo_dev *globalfifo_devp;
struct timertest {
struct timer_list mytimer;
int count;
int delay;
}ttest;
/*在指定回调函数时,并没有给回调函数的实参,
这里的t应该是系统在调用的会传入对应的timer_list,
比如这里是ttest.mytimer*/
void
timer_callback(struct timer_list *t)
{
printk("timer_callback\n");
struct timertest *p = container_of(t, struct timertest, mytimer);
if(--(p->count)) {
/*如果没有这个,那么回调函数只会进入一次,
在调用的时候可以改变回调函数的执行时间*/
mod_timer(t, jiffies+p->delay);
}
else {
printk("timer_callback del\n");
/*也可以在模块退出时删除*/
del_timer(t);
}
//往应用程序发送信号
kill_fasync(&megasas_async_queue, SIGIO, POLL_IN);
return;
}
static int globalfifo_open(struct inode *inode, struct file *filp)
{
return 0;
}
static int globalfifo_release(struct inode *inode, struct file *filp)
{
//fasync_helper(-1, filp, mode, &megasas_async_queue, mode);
return 0;
}
static int globalfifo_fasync(int fd, struct file *filep, int mode)
{
printk(KERN_DEBUG "megasas: fasync_helper\n");
return fasync_helper(fd, filep, mode, &megasas_async_queue);
}
static const struct file_operations globalfifo_fops = {
.owner = THIS_MODULE,
.open = globalfifo_open,
.release = globalfifo_release,
.fasync = globalfifo_fasync,
};
static void globalfifo_setup_cdev(struct globalfifo_dev *dev, int index)
{
int err, devno = MKDEV(globalfifo_major, index);
cdev_init(&dev->cdev, &globalfifo_fops);
dev->cdev.owner = THIS_MODULE;
err = cdev_add(&dev->cdev, devno, 1);
if (err)
printk(KERN_NOTICE "Error %d adding fifo%d", err, index);
}
static int __init globalfifo_init(void)
{
int ret;
dev_t devno = MKDEV(globalfifo_major, 0);
if (globalfifo_major)
ret = register_chrdev_region(devno, 1, "fifo");
else {
ret = alloc_chrdev_region(&devno, 0, 1, "fifo");
globalfifo_major = MAJOR(devno);
}
if (ret < 0)
return ret;
globalfifo_devp = kzalloc(sizeof(struct globalfifo_dev), GFP_KERNEL);
if (!globalfifo_devp) {
ret = -ENOMEM;
goto fail_malloc;
}
globalfifo_setup_cdev(globalfifo_devp, 0);
//定时器
ttest.count = 100;
ttest.delay = 100;
timer_setup(&ttest.mytimer, &timer_callback, 0);
mod_timer(&ttest.mytimer, jiffies+ttest.delay);
return 0;
fail_malloc:
unregister_chrdev_region(devno, 1);
return ret;
}
static void __exit globalfifo_exit(void)
{
cdev_del(&globalfifo_devp->cdev);
kfree(globalfifo_devp);
unregister_chrdev_region(MKDEV(globalfifo_major, 0), 1);
}
module_init(globalfifo_init);
module_exit(globalfifo_exit);
MODULE_AUTHOR("xujia");
MODULE_LICENSE("GPL v2");
//mknod 创建设备节点
//https://www.cnblogs.com/mrlayfolk/p/15858989.html
应用程序
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#define MAX_LEN 100
static void signalio_handler(int signum)
{
printf("receive a signal, signal number:%d\n", signum);
}
int main()
{
int fd, oflags;
/* 以非阻塞方式打开设备文件 */
fd = open("/dev/fifo", O_RDONLY | S_IRUSR | S_IWUSR);
if (fd != -1) {
/* 启动信号驱动机制 */
signal(SIGIO, signalio_handler); //SIGIO信号安装input_handler()作为处理函数
fcntl(fd, F_SETOWN, getpid()); //设置本进程为STDIN_FIFENO文件的拥有者,进程可以接收异步信号
oflags = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, oflags | FASYNC); //设置FASYNC
while (1) {
sleep(100);
}
} else {
printf("device open failure\n");
}
return 0;
}
都是固定套路了。
参考:https://www.cnblogs.com/mrlayfolk/p/15858989.html