0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

使用Linux互斥体实现互斥点灯

CHANBAEK 来源:嵌入式攻城狮 作者:安迪西 2023-04-13 15:13 次阅读

1. 互斥体介绍

互斥访问是指一次只有一个线程可以访问共享资源,不能递归申请互斥体。使用互斥体时要注意如下几点:

  • mutex可导致休眠,因此不能在中断中使用
  • mutex保护的临界区可调用引起阻塞的API函数
  • 必须由mutex的持有者释放mutex,且不能递归上锁和解锁

Linux 内核使用mutex结构体表示互斥体,结构体定义如下所示:

struct mutex {
    /* 1: unlocked, 0: locked, negative: locked, possible waiters */
    atomic_t count;
    spinlock_t wait_lock;
};

互斥体操作相关API函数如下图示:

图片

2. 互斥体实例

本实例中使用互斥体来实现对LED设备的互斥访问,即一次只允许一个应用程序使用LED灯,代码是在pinctrl与gpio子系统下的字符设备驱动框架一文基础上完成的

2.1 修改设备树文件

设备树文件修改与pinctrl与gpio子系统下的字符设备驱动框架文中的修改方法一样,不需要做任何修改

2.2 编写驱动程序

拷贝pinctrl与gpio子系统下的字符设备驱动框架文中的gpioled.c驱动文件,并重命名为mutex.c,对部分代码进行修改,其余保持不变

在设备结构体中,添加互斥体

struct gpioled_dev{
    dev_t devid;              //设备号
    struct cdev cdev;         //cdev字符设备
    struct class *class;      //类
    struct device *device;    //设备
    int major;                //主设备号
    int minor;                //次设备号
    struct device_node *nd;   //设备节点
    int led_gpio;             //所使用的gpio编号
    struct mutex lock;        //互斥体
};

struct gpioled_dev gpioled;   //定义led设备

打开设备时,获取互斥体

static int led_open(struct inode *inode, struct file *filp){
    filp->private_data = &gpioled; //设置私有数据

    if(mutex_lock_interruptible(&gpioled.lock)){
        return -ERESTARTSYS;       //进入休眠后可被信号打断
    } 
#if 0
    mutex_lock(&gpioled.lock);     //休眠后不能被信号打断
#endif
    return 0;
}

关闭设备时,释放互斥锁

static int led_release(struct inode *inode, struct file *filp){
    struct gpioled_dev *dev = filp->private_data;
    mutex_unlock(&dev->lock); //释放互斥锁
    return 0;
}

驱动入口函数中,对互斥体进行初始化

static int __init led_init(void){
    int ret = 0;
    /* 初始化互斥体 */
    mutex_init(&gpioled.lock);  
    /* 设置 LED 所使用的 GPIO */
    /* 1、获取设备节点:gpioled */
    gpioled.nd = of_find_node_by_path("/gpioled");
    ......
    ......
}

2.3 编写测试程序

拷贝pinctrl与gpio子系统下的字符设备驱动框架文中的gpioledApp.c测试程序,并重命名为mutexApp.c,添加模拟占用LED的代码,使测试程序在获取LED驱动使用权后会持续一段时间,添加如下代码

while(1){
    sleep(5);
    cnt++;
    printf("App running times: %d\\r\\n",cnt);
    if(cnt >= 5)
        break;
}

2.4 编译测试

编译驱动程序:当前目录下创建Makefile文件,并使用make命令编译

KERNELDIR := /home/andyxi/linux/kernel/linux-imx-rel_imx_4.1.15_2.1.0_ga_andyxi
CURRENT_PATH := $(shell pwd)
obj-m := mutex.o

build: kernel_modules

kernel_modules:
$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules
clean:
$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean

编译测试程序:无需内核参与,直接编译即可

arm-linux-gnueabihf-gcc mutexApp.c -o mutexApp

运行测试:启动开发板后,加载驱动模块,操作LED灯后,相应时间内再次操作LED时,第二个应用程序会进入休眠,等前面的应用程序运行完后,第二个应用程序会接着运行

depmod                       #第一次加载驱动的时候需要运行此命令
modprobe mutex.ko            #加载驱动
# 打开LED后,每隔5秒会输出一行App running times
./mutexApp /dev/gpioled 1&   # &表示在后台运行APP

图片

#在LED被占用期间,再次操作LED,会因为获取互斥体失败而进入休眠状态,
#等前一条命令运行完并释放互斥锁后才能获取LED使用权
./mutexApp /dev/gpioled 0

图片

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • led
    led
    +关注

    关注

    240

    文章

    23134

    浏览量

    658405
  • 内核
    +关注

    关注

    3

    文章

    1362

    浏览量

    40226
  • Linux
    +关注

    关注

    87

    文章

    11225

    浏览量

    208910
  • 函数
    +关注

    关注

    3

    文章

    4304

    浏览量

    62427
  • 线程
    +关注

    关注

    0

    文章

    504

    浏览量

    19648
收藏 人收藏

    评论

    相关推荐

    详细谈谈Linux中的多线程同步和互斥机制

    互斥:多线程中互斥是指多个线程访问同一资源时同时只允许一个线程对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的;
    的头像 发表于 03-20 09:09 1805次阅读

    Linux高级编程---互斥

    Linux系统里,有很多锁的应用,包括互斥锁,文件锁,读写锁等等,信号量其实也应该是锁的一种。使用锁的目的是为了达到进程、线程之间的同步作用,使共享资源在同一时间内,只有能有一个进程或者线程对它
    发表于 01-13 10:07

    互斥量源码分析测试

    文章目录互斥量源码分析测试参考资料:RTT官网文档关键字:分析RT-Thread源码、stm32、RTOS、互斥量。互斥量在其他书籍中的名称:mutex :互斥锁,
    发表于 08-24 06:01

    信号量和互斥锁的区别

    互斥量用于线程的互斥,信号线用于线程的同步。这是互斥量和信号量的根本区别,也就是互斥和同步之间的区别。互斥:是指某一资源同时只允许一个访问者
    发表于 11-13 17:43 1.3w次阅读
    信号量和<b class='flag-5'>互斥</b>锁的区别

    Linux 多线程互斥互斥

    的。如果操作是原子操作,那么天然的具有互斥同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现
    发表于 04-02 14:47 259次阅读

    详谈Linux操作系统编程的互斥量mutex

    前文提到,系统中如果存在资源共享,线程间存在竞争,并且没有合理的同步机制的话,会出现数据混乱的现象。为了实现同步机制,Linux中提供了多种方式,其中一种方式为互斥锁mutex(也称之为互斥
    的头像 发表于 09-28 15:09 2479次阅读
    详谈<b class='flag-5'>Linux</b>操作系统编程的<b class='flag-5'>互斥</b>量mutex

    详解互斥信号量的概念和运行

    1 、互 斥 信 号 量 1.1 互斥信号量的概念及其作用 互斥信号量的主要作用是对资源实现互斥访问,使用二值信号量也可以实现
    的头像 发表于 10-22 11:57 1.1w次阅读
    详解<b class='flag-5'>互斥</b>信号量的概念和运行

    Linux中的伤害/等待互斥锁介绍

    序言:近期读Linux 5.15的发布说明,该版本合并了实时锁机制,当开启配置宏CONFIG_PREEMPT_RT的时候,这些锁被基于实时互斥锁的变体替代:mutex、ww_mutex
    的头像 发表于 11-06 17:27 2626次阅读

    Linux下线程间通讯--互斥

    互斥锁是一种简单的加锁的方法来控制对共享资源的存取,当多个线程访问公共资源时,为了保证同一时刻只有一个线程独占资源,就可以通过互斥锁加以限制,在一个时刻只能有一个线程掌握某个互斥锁,拥有上锁状态
    的头像 发表于 08-24 15:53 1935次阅读
    <b class='flag-5'>Linux</b>下线程间通讯--<b class='flag-5'>互斥</b>锁

    Free RTOS的互斥信号量

    二进制信号量和互斥量非常相似,但确实有一些细微的区别。互斥包含优先级继承机制,而二进制信号量没有。这使得二进制信号量成为实现同步(任务之间或任务与中断之间)的更好选择,
    的头像 发表于 02-10 15:36 1121次阅读
    Free RTOS的<b class='flag-5'>互斥</b>信号量

    使用Linux原子操作实现互斥点灯

    Linux原子操作是指不能再进一步分割的操作,一般原子操作用于变量或者位操作。Linux内核定义了atomic_t结构来完成整型数据的原子操作,此结构定义在include/
    的头像 发表于 04-13 15:07 843次阅读
    使用<b class='flag-5'>Linux</b>原子操作<b class='flag-5'>实现</b><b class='flag-5'>互斥</b><b class='flag-5'>点灯</b>

    使用Linux信号量实现互斥点灯

    信号量常用于控制对共享资源的访问,有计数型信号量和二值信号量之分。初始化时信号量值大于1的,就是计数型信号量,计数型信号量不能用于互斥访问,它允许多个线程同时访问共享资源。若要互斥访问共享资源,信号量的值就不能大于1,此时就是二值信号量。
    的头像 发表于 04-13 15:12 787次阅读
    使用<b class='flag-5'>Linux</b>信号量<b class='flag-5'>实现</b><b class='flag-5'>互斥</b><b class='flag-5'>点灯</b>

    Linux互斥锁的作用 互斥锁是什么

    1、互斥互斥锁(mutex),在访问共享资源之前对互斥锁进行上锁,在访问完成后释放互斥锁(解锁);对互斥锁进行上锁之后,任何其它试图再次
    的头像 发表于 07-21 11:13 898次阅读

    自旋锁和互斥锁的区别有哪些

    自旋锁 自旋锁与互斥锁很相似,在访问共享资源之前对自旋锁进行上锁,在访问完成后释放自旋锁(解锁);事实上,从实现方式上来说,互斥锁是基于自旋锁来实现的,所以自旋锁相较于
    的头像 发表于 07-21 11:19 9417次阅读

    互斥锁和自旋锁的实现原理

    保护共享资源不被多个线程同时访问。它的实现原理主要包括以下几个方面: 1. 锁的初始化 互斥锁在创建时需要进行初始化,通常包括设置锁的状态为“未锁定”。在某些实现中,还需要初始化锁的等待队列,用于存储等待锁的线程。 2. 锁的
    的头像 发表于 07-10 10:07 410次阅读