【Linux Device Driver】—(2)—Concurrency and Race Conditions——代码
来源:互联网 发布:苹果文字识别软件 编辑:程序博客网 时间:2024/06/05 07:55
做了做这个信号量的实验,不过用到了异步通知,也就是通过内核来通知应用程序(具体就是按键按下后,内核通知应用程序可以进行读操作)!
在《Linux Device Driver》这本书里我查过了,在下章节会介绍到,但是也懒得改代码了,所以就这样贴出来吧,马上也就要写一下异步通知这个很实用的动动。。
这里我用的是互斥锁,还可以设置 O_NONBLOCK 位。
1、驱动程序
①、tiny6410_button_sem.c
#include <linux/io.h>#include <linux/platform_device.h>#include <linux/interrupt.h>#include <linux/irq.h>#include <linux/poll.h>#include <linux/cdev.h>#include <mach/regs-gpio.h>#include <mach/gpio-bank-n.h>#include <mach/gpio-bank-l.h>#include <mach/map.h>MODULE_LICENSE("GPL");static int major;static dev_t devno;static struct cdev cdev;static struct class *tiny6410_class;static struct device *tiny6410_device;static struct fasync_struct *tiny6410_button_fasync;static volatile char key_value;static DEFINE_SEMAPHORE(button_semlock);typedef struct {int irq;/* 中断号 */int num;/* 对应的按键编码 */char *name;/* 对应的按键名称 */} button_irq;button_irq button_irqs[] = {{IRQ_EINT(0), 0, "KEY1"},{IRQ_EINT(1), 1, "KEY2"},{IRQ_EINT(2), 2, "KEY3"},{IRQ_EINT(3), 3, "KEY4"},{IRQ_EINT(4), 4, "KEY5"},{IRQ_EINT(5), 5, "KEY6"},{IRQ_EINT(19), 6, "KEY7"},{IRQ_EINT(20), 7, "KEY8"},};static irqreturn_t button_interrupt(int irq,void *dev_id){button_irq *button_irqs_tmp = (struct button_irq *)dev_id;int down;int number;unsigned tmp;number = button_irqs_tmp->num;switch(number) {case 0: case 1: case 2: case 3: case 4: case 5:tmp = readl(S3C64XX_GPNDAT);down = !(tmp & (1<<number));break;case 6: case 7:tmp = readl(S3C64XX_GPLDAT);down = !(tmp & (1 << (number + 5)));break;default:down = 0;}if (down == !(key_value & (1<<number))) {key_value = down ? (key_value | (1<<number)) : (key_value & ~(1<<number));kill_fasync (&tiny6410_button_fasync, SIGIO, POLL_IN); } return IRQ_RETVAL(IRQ_HANDLED);}static void button_request_irq(void){int i;for(i=0; i<8; i++) {request_irq(button_irqs[i].irq, button_interrupt,IRQ_TYPE_EDGE_BOTH, button_irqs[i].name, (void *)(&button_irqs[i]));}}static void button_free_irq(void){int i;for(i=0; i<8; i++) {free_irq(button_irqs[i].irq, (void *)(&button_irqs[i]));}}static int button_open(struct inode *inode, struct file *filp){if(filp->f_flags & O_NONBLOCK) {if(down_trylock(&button_semlock)) {return -EBUSY;}}else {down(&button_semlock);}button_request_irq();return 0;}static int button_release(struct inode *inode, struct file *filp){up(&button_semlock);button_free_irq();return 0;}static ssize_t button_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos){unsigned long err;err = copy_to_user(buf, &key_value, sizeof(key_value));return err ? -EFAULT : min(sizeof(key_value), size);}static int button_fasync(int fd, struct file *filp, int on){printk("Call button_fasync!\n");return fasync_helper(fd, filp, on, &tiny6410_button_fasync);}static const struct file_operations button_fops ={.owner = THIS_MODULE,.open = button_open,.release = button_release,.read = button_read,.fasync = button_fasync,};static int __init button_sem_init(void){alloc_chrdev_region(&devno, 0, 1, "tiny6410_button_sem");major = MAJOR(devno);/* 初始化cdev */cdev_init(&cdev, &button_fops);cdev.owner = THIS_MODULE;/* 注册cdev */cdev_add(&cdev, MKDEV(major, 0), 1);tiny6410_class = class_create(THIS_MODULE, "tiny6410_sem_class");tiny6410_device = device_create(tiny6410_class, NULL, MKDEV(major, 0), NULL, "tiny6410_button_sem");return 0;}static void __exit button_sem_exit(void){device_destroy(tiny6410_class, devno);class_destroy(tiny6410_class);/* 注销cdev */cdev_del(&cdev);unregister_chrdev_region(MKDEV(major, 0), 1);;}module_init(button_sem_init);moudle_exit(button_sem_exit);
2、测试程序
①、tiny6410_button_sem_app.c
#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <stdio.h>#include <poll.h>#include <signal.h>#include <sys/types.h>#include <unistd.h>#include <fcntl.h>/* tiny6410_button_sem_app.c */ int fd;void button_fasync_signal(int signum){int i;int key_value, last_key_value;read(fd, &key_value, sizeof(key_value));for (i=0; i<8; i++) {if ((key_value & (1<<i)) != (last_key_value & (1<<i))) {printf("KEY%d: %s (key_value = 0x%x)\n",i+1, (key_value & (1<<i)) ? "DOWN" : "UP", key_value);}}last_key_value = key_value;}int main(int argc, char **argv){unsigned char key_val;int ret;int oflags;signal(SIGIO, button_fasync_signal);fd = open("/dev/tiny6410_button_sem", O_RDWR | O_NONBLOCK);if (fd < 0) {printf("can't open!\n");}fcntl(fd, F_SETOWN, getpid());/* Save process ID in filp -> f_owner,告诉内核我要发给谁 */oflags = fcntl(fd, F_GETFL); fcntl(fd, F_SETFL, (oflags | FASYNC));/* 改变fasync 标志,最终会调用到驱动的fasync > fasync_helper;用来初始化/ 释放fasync_struct */while (1) {sleep(1000);}return 0;}
3、测试结果
当时由于没有记录。。。。所以就这样吧。。呵呵。。
- 【Linux Device Driver】—(2)—Concurrency and Race Conditions——代码
- 【Linux Device Driver】—(2)—Concurrency and Race Conditions——原理
- Linux Device Drivers 3rd Edition Concurrency and Race Conditions
- Concurrency and Race Conditions
- 05 Concurrency and Race Conditions .
- 【Linux Device Driver】—(1)—Char Drivers——代码
- 【Linux Device Driver】—(3.1)—ioctl——代码
- MSDN Kernel-Mode Driver Architecture学习笔记(3)——Device Objects and Device Stacks (2)
- Concurrency and Race Condition in Linux 2.6
- linux平台设备驱动架构详解 Linux Platform Device and Driver——神文,非常详细
- Concurrency and Race Condition
- MSDN Kernel-Mode Driver Architecture学习笔记(3)——Device Objects and Device Stacks (1)
- MSDN Kernel-Mode Driver Architecture学习笔记(3)——Device Objects and Device Stacks (3)
- MSDN Kernel-Mode Driver Architecture学习笔记(3)——Device Objects and Device Stacks (4)
- Race Conditions and Reentrant and thread-safe
- 《C++ Concurrency in Action》笔记6 Avoiding problematic race conditions
- 【Tiny6410 And Linux】—(1.5)—driver 设备模型——代码
- 【Tiny6410 And Linux】—(1.4)—device 设备模型——代码
- 微博接口访问权限
- 判断程序是有C编译器编译 还是由c++编译器编译
- 半年的工作总结
- UVa208
- 一条命令搞定虚拟机与实体机文件夹共享
- 【Linux Device Driver】—(2)—Concurrency and Race Conditions——代码
- C++中虚函数工作原理和(虚)继承类的内存占用大小计算
- 写正确函数需要注意的地方:两个有序链表的合并
- F. Letter Grid 动态规划问题
- 3389上的ipv6 -使用ipv6进行远程登录
- 【Linux】Ubuntu下Java编程环境的搭建
- linux下C语言socket网络编程简例
- C++学习之操作符重载
- Extjs-数据存储与传输 Ext.data和Ext.data.Connction