互斥体mutex

参考资料:
《正点原子Linux驱动教程》
《宋宝华 Linux设备驱动开发详解》
 
将信号量的值设置为 1 就可以使用信号量进行互斥访问了,虽然可以通过信号量实现互斥,但是 Linux 提供了一个比信号量更专业的机制来进行互斥,它就是互斥体—mutex。互斥访问表示一次只有一个线程可以访问共享资源,不能递归申请互斥体。在我们编写 Linux 驱动的时候遇到需要互斥访问的地方建议使用 mutex。
Linux内核使用mutex结构体表示互斥体:
struct mutex {
     /* 1: unlocked, 0: locked, negative: locked, possible waiters */
     atomic_t count;
     spinlock_t wait_lock;
};
在使用 mutex 之前要先定义一个 mutex 变量。在使用 mutex 的时候要注意如下几点:
1、mutex 可以导致休眠,因此不能在中断中使用 mutex,中断中只能使用自旋锁。
2、和信号量一样,mutex 保护的临界区可以调用引起阻塞的 API 函数。
3、因为一次只有一个线程可以持有 mutex,因此,必须由 mutex 的持有者释放 mutex。并且 mutex 不能递归上锁和解锁。
 
互斥体的相关API:
0
 
互斥体的使用方法:
struct mutex lock;         /* 定义一个互斥体 */
mutex_init(&lock);         /* 初始化互斥体 */

mutex_lock(&lock);         /* 上锁 */
/* 临界区 */
mutex_unlock(&lock);       /* 解锁 */
 
互斥体使用测试demo:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/mutex.h>

#define DEVICE_NAME "mutex_example"
#define BUF_LEN 80
static int major_number;
static char msg[BUF_LEN];
static short size_of_message;
static struct class* char_class = NULL;
static struct device* char_device = NULL;
static DEFINE_MUTEX(mutex_lock); // 定义互斥体

static int dev_open(struct inode *inodep, struct file *filep){
    if(!mutex_trylock(&mutex_lock)) {
        printk(KERN_ALERT "Mutex is in use by another process");
        return -EBUSY;
    }
    return 0;
}

static int dev_release(struct inode *inodep, struct file *filep){
    mutex_unlock(&mutex_lock);
    return 0;
}

static ssize_t dev_read(struct file *filep, char *buffer, size_t len, loff_t *offset){
    int error_count = 0;
    error_count = copy_to_user(buffer, msg, size_of_message);
    return (error_count==0) ? 0 : -EFAULT;
}

static ssize_t dev_write(struct file *filep, const char *buffer, size_t len, loff_t *offset){
    sprintf(msg, "%s", buffer);
    size_of_message = strlen(msg);
    return len;
}

static struct file_operations fops = {
    .open = dev_open,
    .read = dev_read,
    .write = dev_write,
    .release = dev_release,
};

static int __init mutex_example_init(void){
    major_number = register_chrdev(0, DEVICE_NAME, &fops);
    if (major_number<0){
        printk(KERN_ALERT "Failed to register a major number\n");
        return major_number;
    }
    printk(KERN_INFO "Registered correctly with major number %d\n", major_number);
    char_class = class_create(THIS_MODULE, DEVICE_NAME);
    char_device = device_create(char_class, NULL, MKDEV(major_number, 0), NULL, DEVICE_NAME);
    mutex_init(&mutex_lock);
    return 0;
}

static void __exit mutex_example_exit(void){
    mutex_destroy(&mutex_lock);
    device_destroy(char_class, MKDEV(major_number, 0));
    class_unregister(char_class);
    class_destroy(char_class);
    unregister_chrdev(major_number, DEVICE_NAME);
    printk(KERN_INFO "Goodbye from the mutex example driver!\n");
}

module_init(mutex_example_init);
module_exit(mutex_example_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("lethe1203");
MODULE_DESCRIPTION("mutex demo");

 

 
posted @ 2024-03-25 21:20  lethe1203  阅读(15)  评论(0编辑  收藏  举报