linux内核之读写锁rwlock_t使用入门
如果锁定写锁,则阻止其他地方读或者写,此时写或者读只能等待。
如果锁定写锁,则允许其他的读,但不允许写,写只能等待。
使用流程:
声明一个读写锁:
rwlock_t mylock;
初始化:
rwlock_init(&mylock);
获得写锁:
write_lock(&mylock);
释放写锁:
write_unlock(&mylock);
获得读锁:
read_lock(&mylock);
释放读锁:
read_unlock(&mylock);
以下是驱动模块的代码:
#include <linux/uaccess.h>
#include <linux/fs.h>
#include <linux/stat.h>
#include <linux/cdev.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/irq.h>
#include <linux/mutex.h>
#include <linux/interrupt.h>
#include <linux/bug.h> /* For BUG_ON. */
#include <linux/cpu.h>
#include <linux/init.h> /* Needed for the macros */
#include <linux/kernel.h> /* Needed for pr_info() */
#include <linux/module.h> /* Needed by all modules */
#include <linux/delay.h>
#include <linux/smp.h>
#include <linux/kernel_stat.h>
#include <linux/sched.h>
#include <linux/percpu-defs.h>
#include <linux/wait.h>
#include <linux/gpio/driver.h>
#include <linux/atomic.h>
#include <linux/platform_device.h>
#include <linux/poll.h>
#include <linux/kfifo.h>
#include <linux/rwlock_types.h>
#include <linux/rwlock.h>#define DELAY_CMD_WRITE _IOW('A',0,unsigned int)
#define DELAY_CMD_READ _IOW('A',1,unsigned int)#define MY_MAX_MINORS 1
#define DEVICE_NAME "device name 500"DEFINE_KFIFO(myfifo, char, 1024);struct my_device_data {struct cdev cdev;
};DECLARE_WAIT_QUEUE_HEAD(wq);rwlock_t mylock;static struct my_device_data devs[MY_MAX_MINORS];static int my_open(struct inode *inode, struct file *file) {pr_info("my_open \n");return 0;
}static ssize_t my_write(struct file *filp, const char __user *user_buffer,size_t size, loff_t *offset) {int ret;unsigned int len = 0;pr_info("write");ret = kfifo_from_user(&myfifo, user_buffer, size, &len);if (ret != 0) {pr_err("kfifo_from_user error");return 0;}if (len <= 0)return 0;*offset += len;wake_up(&wq);return len;
}static ssize_t my_read(struct file *filp, char __user *user_buffer,size_t count, loff_t *offset) {int ret;unsigned int len = 0;pr_info("read");ret = kfifo_to_user(&myfifo, user_buffer, count, &len);if (len <= 0)return 0;*offset += len;return len;
}unsigned int my_poll(struct file *flip, struct poll_table_struct *table) {int mask = 0;pr_info("my_poll \n");poll_wait(flip, &wq, table);if (kfifo_is_empty(&myfifo)) {} else {mask |= POLLIN | POLLRDNORM;}return mask;
}int my_close(struct inode *inode, struct file *flip) {pr_info("my_close \n");return 0;
}static long my_ioctl(struct file *file, unsigned int cmd, unsigned long arg) {pr_info("cmd %d\n", cmd);switch (_IOC_NR(cmd)) {case 0: {write_lock(&mylock);pr_info("write start\n");mdelay(5000);pr_info("write end\n");write_unlock(&mylock);break;}case 1: {read_lock(&mylock);pr_info("read start\n");mdelay(3000);pr_info("read end\n");read_unlock(&mylock);break;}default: {pr_info("default: \n");}}return 0;
}static const struct file_operations my_fops = { .owner = THIS_MODULE, .open =my_open, .read = my_read, .write = my_write, .poll = my_poll, .release =my_close, .unlocked_ioctl = my_ioctl,};static dev_t mydev;static __init int my_init(void) {int i;int err;pr_info("a3 init_module\n");err = alloc_chrdev_region(&mydev, 0, MY_MAX_MINORS, DEVICE_NAME);if (err != 0) {return err;}for (i = 0; i < MY_MAX_MINORS; i++) {/* initialize devs[i] fields */cdev_init(&devs[i].cdev, &my_fops);cdev_add(&devs[i].cdev, MKDEV(MAJOR(mydev), i), 1);}
rwlock_init(&mylock);
return 0;
}static void __exit my_exit(void) {int i;pr_info("a3 cleanup_module\n");for (i = 0; i < MY_MAX_MINORS; i++) {/* release devs[i] fields */cdev_del(&devs[i].cdev);}unregister_chrdev_region(mydev, MY_MAX_MINORS);
}module_init(my_init);
module_exit(my_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("81553652@qq.com");
MODULE_DESCRIPTION("andy one-key driver");
MODULE_ALIAS("one-key");
应用程序的测试代码:
#include <stdint.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include <poll.h>#define DELAY_CMD_WRITE _IOW('A',0,unsigned int)
#define DELAY_CMD_READ _IOW('A',1,unsigned int)static void* write01(void *ptr) {int fd = open("/dev/t01", O_RDWR, O_NONBLOCK);if (fd < 0) {perror("open");printf("error open\n");return NULL;}printf("write start \n");ioctl(fd, DELAY_CMD_WRITE, 100);printf("write end \n");sleep(2);close(fd);return NULL;
}static void* read01(void *ptr) {int fd = open("/dev/t01", O_RDWR, O_NONBLOCK);if (fd < 0) {perror("open");printf("error open\n");return NULL;}printf("read start \n");ioctl(fd, DELAY_CMD_READ, 100);printf("read end \n");sleep(1);close(fd);return NULL;
}/*** one write,* two read*/
int main() {pthread_t thread, thread2, thread3;pthread_create(&thread, NULL, write01, NULL);usleep(10*1000);pthread_create(&thread2, NULL, read01, NULL);pthread_join(thread, NULL);pthread_join(thread2, NULL);printf("main exit\n");return EXIT_SUCCESS;
}
测试代码说明:
由于第一个线程是写入,所以第二个线程只能等待写完成之后才能开始读操作。
linux内核之读写锁rwlock_t使用入门相关推荐
- Linux应用开发 - 读写锁
Linux应用开发 - 读写锁 什么时候用到读写锁:多线程开发中,如果少数线程会对共享内存数据修改,多数线程只是读取共享数据的值,就适用于读写锁解决"线程间抢夺资源"的问题. 只要 ...
- linux内核驱动模块开发步骤及实例入门介绍
最近在搞一个linux的项目,其中主要是在编写一些应用模块,对内核及其驱动模块涉及很少,遇到了一些驱动模块的问题时,临时查了些资料,大致了解了一下驱动模块开发的基本步骤和常规步骤,并从网上也收集到了一 ...
- linux操作系统之读写锁
(1)读写锁:只有一把锁,但是有两种状态(读,写) 1)读写锁的三种状态:读锁,写锁,不加锁 2)读写锁特性(12字):写锁优先级高,写独占,读共享 1>写模式加锁时,解锁前,所有对该线程加锁的 ...
- linux 进程间读写锁,Linux系统编程—进程间同步
我们知道,线程间同步有多种方式,比如:信号量.互斥量.读写锁,等等.那进程间如何实现同步呢?本文介绍两种方式:互斥量和文件锁. ##互斥量mutex 我们已经知道了互斥量可以用于在线程间同步,但实际上 ...
- Linux线程同步读写锁 rwlock
读写锁比mutex有更高的适用性,可以多个线程同时占用读模式的读写锁,但是只能一个线程占用写模式的读写锁. 1. 当读写锁是写加锁状态时,在这个锁被解锁之前,所有试图对这个锁加锁的线程都会被阻塞: 2 ...
- linux内核 noreturn,读《ARM Linux 内核源代码剖析》.......第13章 setup_processor()
setup_processor首先是查找保存相应处理器信息的结构体,然后根据结构体里的值,对处理器相关的各种变量进行设置. setup_processor static void __init set ...
- 【Linux内核】RW读写锁机制
读写锁机制 Linux内核中读写锁的机制是一种多读单写的锁机制,它允许多个读操作同时进行,但只能有一个写操作进行.当有写操作时,所有读操作都会被阻塞,直到写操作完成. 在内核中,读写锁主要由以下两个结 ...
- 深度解析Linux读写锁逻辑
一.Linux为何会引入读写锁? 除了mutex,在linux内核中,还有一个经常用到的睡眠锁就是rw semaphore(后文简称为rwsem),它到底和mutex有什么不同呢?为何会有rw sem ...
- linux 进程 读写锁,linux 下实现高性能读写锁(read/write lock)
前一篇文章分析了Windows slim read/write lock的工作原理.我们知道它的设计相当精妙,于是我们可以借鉴它的思路来设计linux下的读写锁. 在这个读写锁的设计上,需要注意的是l ...
最新文章
- J2EE 第二阶段项目之编写代码(四)
- OpenStack 的 SR-IOV 虚拟机热迁移
- qpython3安装lxml_centos python安装lxml报错
- 深度 | 阿里云蒋江伟:什么是真正的云原生?
- 被阻塞的线程唤醒后的逻辑
- C#实现树的双亲表示法
- java hashtable 修改_Java Hashtable computeIfAbsent()用法及代码示例
- 苹果系统itunes连iphone连不上服务器,iphone连不上itunes怎么办,iphone连不上itunes的解决办法...
- TPS和QPS的区别和理解
- 丘成桐:数理与人文(官方完整版PDF下载)(公号回复“丘成桐数学”下载PDF典型资料,欢迎转发、赞赏支持科普)
- 本地图片转换Base64的方法,Base64码转换为本地图片
- 读书笔记-指数基金投资指南
- 巴西电商Olist数据分析项目:SQL+FineBI
- 2022无线蓝牙耳机选哪个?盘点超热门的蓝牙耳机品牌推荐
- UOJ#748-[UNR #6]机器人表演【dp】
- hosts文件如何修改?已解决
- sd和sem啥区别_SD与SEM区别
- Python(详解)找出一个整数的所有因子---显示所有的最小因子--素因子
- 网页后缀php,网页后缀php有什么含义
- LTE学习-RACH(1)