文章目录
- 前言
- 互斥锁的定义
- 互斥锁的数据结构
- 互斥锁的注意事项
- 互斥锁API函数
- 互斥锁的使用示例
- 结语
前言
上篇我们讲过信号量,本篇讲下互斥体。本篇内核源码以内核5.10为例进行讲解
互斥锁的定义
其实信号量的值设置为1就可以使用信号量进行互斥访问了,虽然信号量也可以实现互斥,但是Linux内核提供了一个比信号量更专业的机制来实现互斥,他就是互斥体-mutex,互斥体相对于信号量要简单轻便一些,且比信号量执行速度更快
在软件中保证一个时刻只有一个线程执行读写操作,那么这种在微观上确保一个时刻只允许一个线程执行特定的代码段的问题,称为互斥问题。
互斥锁的数据结构
file: include/linux/mutex.h
struct mutex {
atomic_long_t owner;
spinlock_t wait_lock;
struct list_head wait_list;
}
成员解析:
- wait_lock: 用来保护互斥体数据结构里的wait_list等待队列成员
- owner: 用来允许进入临界区的内核执行的路径,0代表锁没有被持有,非零代表锁被持有最低三位来表示。(4.x内核是count变量成员,1代表锁没有被进程持有,0代表锁被进程持有,负数代表有进程等待)
互斥锁的注意事项
- 同一时刻只有一个线程可以持有互斥锁
- 只有锁持有者可以解锁。不能在一个进程中持有互斥锁,而在另一个进程中释放它。因此互斥锁不适合内核与用户空间复杂的同步场景,信号量和读写信号量比较适合
- 不允许递归地加锁和解锁
- 当进程持有互斥锁时,进程不可以退出
- 互斥锁必须使用官方API来初始化
- 互斥锁可以睡眠,所以不允许在中断处理程序或者中断下半部中使用,例如tasklet、定时器等。
互斥锁API函数
有关互斥体的API函数如表所示
互斥锁的使用示例
自己写个应用模拟打开驱动程序,执行两个应用程序,驱动程序如下所示
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <asm/uaccess.h>
#include <asm/io.h>
/* gpioled设备结构体 */
struct gpioled_dev{
...
int dev_status; /* 设备使用状态,0,设备未使用;>0,设备已经被使用 */
struct mutex lock; /* 互斥锁变量 */
};
static int led_open(struct inode *inode, struct file *filp)
{
unsigned long flags;
filp->private_data = &gpioled; /* 设置私有数据 */
mutex_lock(&gpioled.lock); /* 加锁互斥体 */
return 0;
}
static int led_release(struct inode *inode, struct file *filp)
{
unsigned long flags;
struct gpioled_dev *dev = filp->private_data;
mutex_unlock(&dev->lock); /* 解锁互斥体 */
return 0;
}
/* 设备操作函数 */
static struct file_operations gpioled_fops = {
.owner = THIS_MODULE,
.open = led_open,
.read = led_read,
.write = led_write,
.release = led_release,
};
static int __init led_init(void)
{
/* 初始化互斥体 */
mutex_init(&gpioled.lock, 1);
...
}
当多个应用同时打开的话,当第一个应用程序调用驱动正常执行,在执行第二个应用程序再次调用驱动的时候会因为获取不到互斥锁导致应用程序进入休眠等待,直到第一个应用程序运行完释放互斥锁释放驱动后,第二个应用程序就会释放互斥锁从而释放资源,可以继续打开
结语
本篇的主要是记录下互斥体的使用,有啥疑问欢迎文末留言
作者潘小帅, 是一名Linux底层爱好者,平时写写技术原创文章,徒步,旅游,看电影的爱好,喜欢我的文章可以点赞收藏+关注,感谢你的支持,微信公众号【Linux随笔录】
本文由mdnice多平台发布