内核异步通知的例子

       内核异步IO的介绍见http://blog.chinaunix.net/uid-25014876-id-62725.html,本文讲原文的例子进行了一定的改造,通过定义器的方法,定时时间一到就通过异步通知的方法发给上层的应用,应用捕捉到相应的信号后,执行相应的操作。

#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <asm/uaccess.h>
#include <linux/errno.h>
#include <linux/device.h>
#include <linux/timer.h>


#define DEBUG_SWITCH    1
#if DEBUG_SWITCH
	#define P_DEBUG(fmt, args...)   printk("<1>" "<kernel>[%s]"fmt, __FUNCTION__, ##args)
#else
	#define P_DEBUG(fmt, args...)   printk("<7>" "<kernel>[%s]"fmt, __FUNCTION__, ##args)
#endif

#define DEV_SIZE 100

struct test_t{
	char kbuf[DEV_SIZE];
	unsigned int major;
	unsigned int minor; 
	dev_t devno;
	struct timer_list timer;
	struct cdev test_cdev;
	struct fasync_struct *async_queue;
	struct class *asyn_class;
};

static struct test_t my_dev;

int test_open(struct inode *node, struct file *filp)
{
	struct test_t *dev;
	dev = container_of(node->i_cdev, struct test_t, test_cdev);
	filp->private_data = dev;
	return 0;
}

int test_fasync (int fd, struct file *filp, int mode)
{
	struct test_t *dev = filp->private_data;
	return fasync_helper(fd, filp, mode, &dev->async_queue);
}

int test_close(struct inode *node, struct file *filp)
{
	test_fasync(-1, filp, 0);
	return 0;
}

struct file_operations test_fops = {
	.open    = test_open,
	.release = test_close,
	.fasync  = test_fasync,
};

static void timer_function(unsigned long arg) 
{ 
	mod_timer(&my_dev.timer, jiffies + 2*HZ);
	if (my_dev.async_queue)
	kill_fasync(&my_dev.async_queue, SIGIO, POLL_IN);
}

static void timer_init(void)
{
	init_timer(&my_dev.timer);
	my_dev.timer.data=0;
	my_dev.timer.function=timer_function;
	my_dev.timer.expires=jiffies+2*HZ;
	add_timer(&my_dev.timer);
}

static int __init test_init(void)	
{
	int result = 0;
	P_DEBUG("%s\n",__FUNCTION__);
	my_dev.major = 0;
	my_dev.minor = 0;
	if(my_dev.major){						
		my_dev.devno = MKDEV(my_dev.major, my_dev.minor);
		result = register_chrdev_region(my_dev.devno, 1, "asynchronous_notification");
	}else{
		result = alloc_chrdev_region(&my_dev.devno, my_dev.minor, 1, "asynchronous_notification");
		my_dev.major = MAJOR(my_dev.devno);
		my_dev.minor = MINOR(my_dev.devno);
	}

	if(result < 0){
		P_DEBUG("register devno errno!\n");
		goto err0;
	}

	printk("major[%d] minor[%d]\n", my_dev.major, my_dev.minor);

	cdev_init(&my_dev.test_cdev, &test_fops);
	my_dev.test_cdev.owner = THIS_MODULE;
	result = cdev_add(&my_dev.test_cdev, my_dev.devno, 1);
	if(result < 0){
		P_DEBUG("cdev_add errno!\n");
		goto err1;
	}
	my_dev.asyn_class=class_create(THIS_MODULE,"asyn_class");
	if(IS_ERR(my_dev.asyn_class))
	{
		result=PTR_ERR(my_dev.asyn_class);
		goto err2;
	}
	device_create(my_dev.asyn_class,NULL,my_dev.devno,NULL,"asynchronous_notification");
	timer_init();
	P_DEBUG("%s successful\n",__FUNCTION__);
	return 0;
err2:
	cdev_del(&my_dev.test_cdev);
err1:
	unregister_chrdev_region(my_dev.devno, 1);
err0:
	return result;
}

static void __exit test_exit(void)
{
	printk("%s\n",__FUNCTION__);
	my_dev.async_queue=NULL;
	del_timer(&my_dev.timer);
	device_destroy(my_dev.asyn_class,my_dev.devno);  
    	class_destroy(my_dev.asyn_class);  
	cdev_del(&my_dev.test_cdev);
	unregister_chrdev_region(my_dev.devno, 1);	
}

module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL");

相应的APP为app.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>
#include <unistd.h>
#include <signal.h>

unsigned int flag;

void sig_handler(int sig)
{
	printf("%s\n", __FUNCTION__);
}

int main(void)
{
	char buf[20];
	int fd;	
	int f_flags;
	flag = 0;

	fd = open("/dev/asynchronous_notification", O_RDWR);
	if(fd < 0)
	{
		perror("open");
		return -1;
	}
	
	signal(SIGIO, sig_handler);
	fcntl(fd, F_SETOWN, getpid());
	f_flags = fcntl(fd, F_GETFL);
	fcntl(fd, F_SETFL, FASYNC | f_flags);

	while(1)
	{
		printf("waiting \n");
		sleep(4);
	}
	printf("finish\n");
	close(fd);
	return 0;
}

把Makefile文件也附上

ifeq ($(KERNELRELEASE),)  
KERNELDIR ?= /Android源码根路径/kernel/
DBG_CROSS_COMPILE ?= /Android源码根路径/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-
EXTRA_LIBS += -lpthread -static
CC=arm-linux-gcc
EXEC =  app
OBJS =  app.o
PWD :=$(shell pwd)  
all: $(EXEC)  modules
$(EXEC): $(OBJS)
	$(CC) $(LDFLAGS) -o $@ $(OBJS)  $(EXTRA_LIBS)
modules:  
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules  
modules_install:  
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install  
clear:  
	rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order  Module.symvers  *.elf *.elf2flt *.gdb *.o 
else  
     obj-m:= asynchronous_notification.o  
endif  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值