linux设备驱动--并发与竞态之信号量
来源:互联网 发布:舆情监控软件破解版 编辑:程序博客网 时间:2024/04/30 10:05
信号量(semaphore)是用于保护临界区的一种常用手段。与自旋锁相同,只有得到信号量的进程才能执行临界区代码。但不同的是,当获取不到信号量时,进程不会“自旋”而是进入休眠等待状态。
To use semaphores,kernel code must include <asm/semaphore.h>.
信号量的初始化:
直接创建信号量:
void sema_init(struct semaphore *sem, int val);
声明和初始化互斥体的宏:
DECLARE_MUTEX_LOCKED(name);
动态分配互斥体:
void init_MUTEX(struct semaphore *sem);
void init_MUTEX_LOCKED(struct semaphore *sem);
获得信号量:
void down(struct semaphore *sem);
int down_interruptible(struct semaphore *sem);
int down_trylock(struct semaphore *sem);
释放信号量:
void up(struct semaphore *sem);
正如读写锁,信号量也有读写信号量。
信号量对所有的调用者执行互斥。但很多任务可以划分两种不同的工作类型:一些任务只需要读取受保护的数据结构,而其他的来做写入的动作。允许多个并发的读取是可能的,这样做会大大提高性能。
一个rwsem可允许一个写入者或无限多个读取者拥有该信号量。写入者具有更高的优先级;所以在读远远大于写的时候用rwsem会大大提高新能。在APUE中,在讲到线程同步时提到了读写锁,那里的读写锁同样是非常适合于对数据结构读的次数远大于写的情况。
下面继续用scull的例子来看下使用信号量实现设备文件只能被一个进程打开的例子:
代码添加如下:
static DECLARE_MUTEX(scull_lock);//define mutexint scull_open(struct inode *inode, struct file *filp){struct scull_dev *dev; /* device information */dev = container_of(inode->i_cdev, struct scull_dev, cdev);filp->private_data = dev; /* for other methods */if(down_trylock(&scull_lock)){return -EBUSY;}return 0; /* success */}int scull_release(struct inode *inode, struct file *filp){up(&scull_lock);return 0;}
用./app 测试表明该设备文件只能被一个进程打开。
接下来继续完成增加并发控制的scull驱动。要注意的是信号量必须在scull设备对系统其他部分可用前被初始化。
代码改动如下:
/* * Representation of scull quantum sets. */struct scull_dev {unsigned char mem[SCULL_SIZE];struct cdev cdev; /* Char device structure*/struct semaphore sem; /*semaphore*/};
ssize_t scull_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos){unsigned long p = *f_pos;int ret = 0;struct scull_dev *dev = filp->private_data;if(p >= SCULL_SIZE)return count ? -ENXIO : 0 ;if(count > SCULL_SIZE - p)count = SCULL_SIZE - p;if(down_interruptible(&dev->sem))return -ERESTARTSYS; if(copy_to_user(buf, (void *)(dev->mem + p), count)){ret = - EFAULT;}else{*f_pos += count;ret = count;printk(KERN_WARNING "read %d bytes from %d\n", count, p);}printk(KERN_WARNING "ret: %d\n",ret);up(&dev->sem);return ret;}ssize_t scull_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos){unsigned long p = *f_pos;int ret = 0;struct scull_dev *dev = filp->private_data;if(p >= SCULL_SIZE )return count ? -ENXIO : 0 ;if(count > SCULL_SIZE - p)count = SCULL_SIZE - p;if(down_interruptible(&dev->sem))return -ERESTARTSYS;if(copy_from_user(dev->mem + p, buf, count)){ret = -EFAULT;}else{*f_pos += count;ret = count;printk(KERN_WARNING "write %d bytes to %d\n", count , p);}up(&dev->sem);return ret;}
这样,用./app测试,可以多个进程同时打开访问scull设备文件,但对于文件的读写,是有互斥控制的。
- linux设备驱动--并发与竞态之信号量
- linux设备驱动--并发与竞态之原子操作
- linux设备驱动--并发与竞态之自旋锁
- linux设备驱动--并发与竞态之原子操作
- linux设备驱动开发学习之旅--linux设备驱动中的并发与竞态
- Linux设备驱动中的并发控制---信号量
- Linux 设备驱动--- 并发 之- 信号量 --- semaphore --- down_interruptible --- 按键信号量使用
- Hasen的linux设备驱动开发学习之旅--linux设备驱动中的并发与竞态
- linux字符设备驱动 并发与竞态
- Linux驱动之并发与竞态
- Linux 设备驱动 ====> 并发控制 --- 信号量与互斥体
- Linux 设备驱动 ====> 并发控制 --- 信号量与互斥体
- Linux 设备驱动 ====> 并发控制 --- 信号量与互斥体
- linux设备驱动的并发与竞争
- Linux驱动并发处理---信号量
- linux驱动之并发与竟态
- 深入浅出Linux设备驱动之并发控制
- 深入浅出Linux设备驱动之并发控制
- 文件的输入输出函数
- TCP和UDP,还有与socket的区别
- 闭包-函数式编程
- HDU--4006(The kth great number)
- extjs表单第一个textfield获得焦点
- linux设备驱动--并发与竞态之信号量
- 【每日面试题】在字符串中删除特定的字符
- ExtJs2.0学习系列--索引贴
- Ext.form提交 ashx时 报“文档的顶层无效”的处理办法
- 并发连接数 算法
- zoj 3230Solving the Problems//优先队列
- Ext 表单异步提交
- 标准输入输出函数
- 关于 linux 编译预处理 ifdef的使用