高级字符驱动程序操作之异步通知IO(实践篇)

 

1. async.c 主要展示异步通知机制在驱动程序中的实现

 

  1. #include <linux/module.h>   
  2. #include <linux/init.h>   
  3.   
  4. #include <linux/fs.h>     /* everything... */   
  5. #include <linux/types.h>  /* size_t */   
  6. #include <linux/cdev.h>   
  7. #include <linux/fcntl.h>   
  8. #include <asm/uaccess.h> /* copy user */   
  9. #include <linux/poll.h> /* POLL_IN */   
  10.   
  11. MODULE_AUTHOR("victorsummer");  
  12. MODULE_LICENSE("Dual BSD/GPL");  
  13.   
  14.   
  15. static int async_major = 0;  
  16. struct fasync_struct *async_queue;  
  17. static char *buffer = NULL;  
  18.   
  19. ssize_t async_read (struct file *filp, char __user *buf, size_t count, loff_t *pos)  
  20. {  
  21.     if(buffer)  
  22.         copy_to_user(buf, buffer, count);   
  23.   
  24.     return count;   
  25. }  
  26.   
  27. ssize_t async_write (struct file *filp, const char __user *buf, size_t count,  
  28.         loff_t *pos)  
  29. {  
  30.     if(buffer)  
  31.         copy_from_user(buffer, buf, count);  
  32.     if(async_queue)  
  33.         kill_fasync(&async_queue, SIGIO, POLL_IN);  
  34.     return count;  
  35. }  
  36.   
  37. static int async_fasync(int fd, struct file *filp, int mode)  
  38. {  
  39.     return fasync_helper(fd, filp, mode, &async_queue);  
  40. }  
  41.   
  42. int async_release(struct inode *inode, struct file *filp)  
  43. {  
  44.     async_fasync(-1, filp, 0);  
  45.     return 0;  
  46. }  
  47.   
  48. static int async_open(struct inode *inode, struct file *filp)  
  49. {  
  50.     return nonseekable_open(inode, filp);  
  51. }  
  52.   
  53.   
  54. struct file_operations async_fops = {  
  55.     .owner = THIS_MODULE,  
  56.     .read =  async_read,  
  57.     .write = async_write,  
  58.     .fasync = async_fasync,  
  59.     .release = async_release,  
  60.     .open = async_open,  
  61. };  
  62.   
  63. int async_init(void)  
  64. {  
  65.     int result;  
  66.     dev_t dev = 0;  
  67.     
  68.     struct cdev *async_cdev = cdev_alloc();  
  69.   
  70.     if (async_major) {  
  71.         dev = MKDEV(async_major, 0);  
  72.         result = register_chrdev_region(dev, 1, "async");  
  73.     } else {  
  74.         result = alloc_chrdev_region(&dev, 0, 1, "async");  
  75.         async_major = MAJOR(dev);  
  76.     }  
  77.     if (result < 0) {  
  78.         return result;  
  79.     }  
  80.   
  81.     if(!buffer)  
  82.         buffer = kmalloc(1024*sizeof(char), GFP_KERNEL);  
  83.   
  84.     cdev_init(async_cdev, &async_fops);  
  85.     async_cdev->owner = THIS_MODULE;  
  86.     cdev_add(async_cdev, dev, 1);  
  87.   
  88.     return 0;  
  89. }  
  90.   
  91. void async_cleanup(void)  
  92. {  
  93.     dev_t devno;  
  94.     if(buffer)  
  95.     {  
  96.         kfree(buffer);  
  97.         buffer = NULL;  
  98.     }  
  99.     devno = MKDEV(async_major, 0);  
  100.     unregister_chrdev_region(devno, 1);  
  101. }  
  102.   
  103. module_init(async_init);  
  104. module_exit(async_cleanup);  
#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

 

  1. KERNELDIR = /usr/src/linux-headers-2.6.31-14-generic  
  2. PWD := $(shell pwd)  
  3.   
  4. obj-m := async.o   
  5.   
  6. modules:  
  7.     $(MAKE) -C $(KERNELDIR) M=$(PWD) modules  
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 异步读取程序

 

  1. #include <unistd.h>  
  2. #include <sys/stat.h>  
  3. #include <fcntl.h>  
  4. #include <stdlib.h>  
  5. #include <stdio.h>  
  6. #include <signal.h>  
  7. #include <string.h>   
  8.   
  9. int async_fd;  
  10. void sig_handler(int signo)  
  11. {  
  12.     int code;  
  13.   
  14.         if (signo==SIGIO)  
  15.         {  
  16.         char *buf = malloc(30*sizeof(char));  
  17.   
  18.         if ((code=read(async_fd, buf, 24)) == -1)   
  19.             printf("read err! code=%d /n", code);  
  20.   
  21.         else     
  22.             printf("read ok! code=%d /n", code);  
  23.         printf("Read %s from async module /n", buf);  
  24.         free(buf);  
  25.         }  
  26.         return;  
  27. }  
  28.   
  29. int main()  
  30. {  
  31.         struct sigaction action;  
  32.   
  33.         memset(&action, 0, sizeof(action));  
  34.         action.sa_handler = sig_handler;  
  35.         action.sa_flags = 0;      
  36.   
  37.     sigaction(SIGIO, &action, NULL);  
  38.   
  39.     async_fd = open("/dev/async", O_RDONLY);  
  40.     fcntl(async_fd, F_SETOWN, getpid());  
  41.     fcntl(async_fd, F_SETFL, fcntl(STDIN_FILENO, F_GETFL) | FASYNC);  
  42.   
  43.     while(1)  
  44.     {  
  45.             sleep(86400);  
  46.     }  
  47.   
  48.     close(async_fd);  
  49.     exit(0);  
  50. }  
#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 写入程序

 

  1. #include <unistd.h>  
  2. #include <sys/stat.h>  
  3. #include <fcntl.h>  
  4. #include <stdlib.h>  
  5. #include <stdio.h>   
  6.   
  7. int main()  
  8. {  
  9.     char *write_buffer = "Hello, Character driver!";  
  10.   
  11.     int async_fd;  
  12.   
  13.     int code;  
  14.   
  15.       
  16.   
  17.     async_fd = open("/dev/async",O_WRONLY );  
  18.   
  19.   
  20.   
  21.     while(*write_buffer != '/0')  
  22.     {    
  23.         code = write(async_fd , write_buffer , 24);  
  24.         printf("Write %d bytes to async_fd/n", code);  
  25.         write_buffer += code;  
  26.     }  
  27.   
  28.     close(async_fd);  
  29.   
  30.     exit(0);  
  31. }  
#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

 

  1. all : async_testw.o async_testr.o  
  2.         gcc -o async_testw.o async_testw.c  
  3.         gcc -o async_testr.o async_testr.c  
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

 

转载于:https://www.cnblogs.com/sankye/articles/2234654.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值