1. async.c 主要展示异步通知机制在驱动程序中的实现
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/fs.h> /* everything... */
- #include <linux/types.h> /* size_t */
- #include <linux/cdev.h>
- #include <linux/fcntl.h>
- #include <asm/uaccess.h> /* copy user */
- #include <linux/poll.h> /* POLL_IN */
- MODULE_AUTHOR("victorsummer");
- MODULE_LICENSE("Dual BSD/GPL");
- static int async_major = 0;
- struct fasync_struct *async_queue;
- static char *buffer = NULL;
- ssize_t async_read (struct file *filp, char __user *buf, size_t count, loff_t *pos)
- {
- if(buffer)
- copy_to_user(buf, buffer, count);
- return count;
- }
- ssize_t async_write (struct file *filp, const char __user *buf, size_t count,
- loff_t *pos)
- {
- if(buffer)
- copy_from_user(buffer, buf, count);
- if(async_queue)
- kill_fasync(&async_queue, SIGIO, POLL_IN);
- return count;
- }
- static int async_fasync(int fd, struct file *filp, int mode)
- {
- return fasync_helper(fd, filp, mode, &async_queue);
- }
- int async_release(struct inode *inode, struct file *filp)
- {
- async_fasync(-1, filp, 0);
- return 0;
- }
- static int async_open(struct inode *inode, struct file *filp)
- {
- return nonseekable_open(inode, filp);
- }
- struct file_operations async_fops = {
- .owner = THIS_MODULE,
- .read = async_read,
- .write = async_write,
- .fasync = async_fasync,
- .release = async_release,
- .open = async_open,
- };
- int async_init(void)
- {
- int result;
- dev_t dev = 0;
- struct cdev *async_cdev = cdev_alloc();
- if (async_major) {
- dev = MKDEV(async_major, 0);
- result = register_chrdev_region(dev, 1, "async");
- } else {
- result = alloc_chrdev_region(&dev, 0, 1, "async");
- async_major = MAJOR(dev);
- }
- if (result < 0) {
- return result;
- }
- if(!buffer)
- buffer = kmalloc(1024*sizeof(char), GFP_KERNEL);
- cdev_init(async_cdev, &async_fops);
- async_cdev->owner = THIS_MODULE;
- cdev_add(async_cdev, dev, 1);
- return 0;
- }
- void async_cleanup(void)
- {
- dev_t devno;
- if(buffer)
- {
- kfree(buffer);
- buffer = NULL;
- }
- devno = MKDEV(async_major, 0);
- unregister_chrdev_region(devno, 1);
- }
- module_init(async_init);
- module_exit(async_cleanup);
2. Makefile
- KERNELDIR = /usr/src/linux-headers-2.6.31-14-generic
- PWD := $(shell pwd)
- obj-m := async.o
- modules:
- $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
3. async_testr.c 异步读取程序
- #include <unistd.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <signal.h>
- #include <string.h>
- int async_fd;
- void sig_handler(int signo)
- {
- int code;
- if (signo==SIGIO)
- {
- char *buf = malloc(30*sizeof(char));
- if ((code=read(async_fd, buf, 24)) == -1)
- printf("read err! code=%d /n", code);
- else
- printf("read ok! code=%d /n", code);
- printf("Read %s from async module /n", buf);
- free(buf);
- }
- return;
- }
- int main()
- {
- struct sigaction action;
- memset(&action, 0, sizeof(action));
- action.sa_handler = sig_handler;
- action.sa_flags = 0;
- sigaction(SIGIO, &action, NULL);
- async_fd = open("/dev/async", O_RDONLY);
- fcntl(async_fd, F_SETOWN, getpid());
- fcntl(async_fd, F_SETFL, fcntl(STDIN_FILENO, F_GETFL) | FASYNC);
- while(1)
- {
- sleep(86400);
- }
- close(async_fd);
- exit(0);
- }
4. async_testw.c 写入程序
- #include <unistd.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <stdlib.h>
- #include <stdio.h>
- int main()
- {
- char *write_buffer = "Hello, Character driver!";
- int async_fd;
- int code;
- async_fd = open("/dev/async",O_WRONLY );
- while(*write_buffer != '/0')
- {
- code = write(async_fd , write_buffer , 24);
- printf("Write %d bytes to async_fd/n", code);
- write_buffer += code;
- }
- close(async_fd);
- exit(0);
- }
5. Makefile
- all : async_testw.o async_testr.o
- gcc -o async_testw.o async_testw.c
- gcc -o async_testr.o async_testr.c
6. 开始测试
装载驱动程序
sudo insmod ./async.ko
查看主设备号,假设为250
cat /proc/devices
建立设备节点
sudo mknod /dev/async c 250 0
更改权限
sudo chgrp staff /dev/async
sudo chmod 664 /dev/async
在终端1中打开异步读取程序,程序开始sleep
sudo ./async_testr.o
在终端2中打开写入程序
sudo ./async_testw.o
结果:
终端2打印:
Write 24 bytes to async_fd
终端1打印:
read ok! code=24
Read Hello, Character driver! from async module