i.MX6ULL终结者Linux并发与竞争实验互斥体实验

前面我们使用原子操作、自旋锁和信号量实现了对 LED 灯的互斥访问,但是最适合互斥的就是互斥体 mutex 了。本节我们来学习一下如何使用 mutex 实现对 LED 灯的互斥访问。

1 编写驱动程序

本实验例程路径:i.MX6UL终结者光盘资料/06_Linux驱动例程/07_gpioled_mutex
创建gpioled_mutex.c,内容如下(有省略) :

1 #include <linux/types.h>
  2 #include <linux/kernel.h>
......
 23 /* gpioled 设备结构体 */
 24 struct gpioled_dev{
 25         dev_t devid; /* 设备号 */
 26         struct cdev cdev; /* cdev */
 27         struct class *class; /* 类 */
 28         struct device *device; /* 设备 */
 29         int major; /* 主设备号 */
 30         int minor; /* 次设备号 */
 31         struct device_node *nd; /* 设备节点 */
 32         int led_gpio; /* led 所使用的 GPIO 编号*/
 33         struct mutex lock; /* 互斥体 */
 34 };
 35 
 36 struct gpioled_dev gpioled; /* led 设备 */
 37 
 38 /*
 39  * @description : 打开设备
 40  * @param – inode : 传递给驱动的 inode
 41  * @param - filp : 设备文件,file 结构体有个叫做 private_data 的成员变量
 42  * 一般在 open 的时候将 private_data 指向设备结构体。
 43  * @return : 0 成功;其他 失败
 44  */
 45 static int led_open(struct inode *inode, struct file *filp)
 46 {
 47         filp->private_data = &gpioled; /* 设置私有数据 */
 48 
 49         /* 获取互斥体,可以被信号打断 */
 50         if (mutex_lock_interruptible(&gpioled.lock)) {
 51                 return -ERESTARTSYS;
 52         }
 53 #if 0
 54         mutex_lock(&gpioled.lock); /* 不能被信号打断 */
 55 #endif
 56 
 57         return 0;
 58 }
......
104 /*
105  * @description : 关闭/释放设备
106  * @param – filp : 要关闭的设备文件(文件描述符)
107  * @return : 0 成功;其他 失败
108  */
109 static int led_release(struct inode *inode, struct file *filp)
110 {
111         struct gpioled_dev *dev = filp->private_data;
112 
113         /* 释放互斥锁 */
114         mutex_unlock(&dev->lock);
115 
116         return 0;
117 }
118 
119 /* 设备操作函数 */
120 static struct file_operations gpioled_fops = {
121         .owner = THIS_MODULE,
122         .open = led_open,
123         .read = led_read,
124         .write = led_write,
125         .release = led_release,
126 };
127 
128 /*
129  * @description : 驱动入口函数
130  * @param : 无
131  * @return : 无
132  */
133 static int __init led_init(void)
134 {
135         int ret = 0;
136 
137         /* 初始化互斥体 */
138         mutex_init(&gpioled.lock);
......
198         return 0;
199 }
......
214 
215 module_init(led_init);
216 module_exit(led_exit);
217 MODULE_LICENSE("GPL");
218 MODULE_AUTHOR("topeet");

第 33 行,定义互斥体 lock。
第 45~58 行,在 open 函数中调用 mutex_lock_interruptible 或者 mutex_lock 获取 mutex,成功的话就表示可以使用 LED 灯,失败的话就会进入休眠状态,和信号量一样。
第 114 行,在 release 函数中调用 mutex_unlock 函数释放 mutex,这样其他应用程序就可以获取 mutex 了。
第 138 行,在驱动入口函数中调用 mutex_init 初始化 mutex。
互斥体和二值信号量类似,只不过互斥体是专门用于互斥访问的。

2 编写应用测试程序

应用测试程序使用38.1.2中的应用测试程序即可。

3 运行测试

1、编译驱动程序
添加Makefile文件,修改obj-m的值为 gpioled_mutex.o,内容如下:

KERNELDIR := /home/topeet/kernel
CURRENT_PATH := $(shell pwd)
obj-m := gpioled_mutex.o

build: kernel_modules

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

首先我们在终端输入两个命令(设置两个环境变量):

export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-

然后使用“make”命令进行编译,生成gpioled_mutex.ko驱动模块文件。
2、运行测试
将编译好的gpioled_mutex.ko驱动模块文件拷贝到/lib/modules/4.1.15目录下(检查开发板根文件系统中有没有“/lib/modules/4.1.15”这个目录,如果没有的话需要自行创建一下。开发板中使用的是光盘资料里面提供的busybox文件系统,光盘资料的“i.MX6UL终结者光盘资料\08_开发板系统镜像\03_文件系统镜像\01_Busybox文件系统”目录下)。输入下面命令加载模块:

depmod
modprobe gpioled_mutex

驱动模块加载成功如图 3.1所示:
在这里插入图片描述

图 3.1

驱动模块加载成功后,使用gpioled_atomic_test应用测试程序进行测试,测试流程和原子变量测试一样。使用下面的命令打开LED灯:
./gpioled_atomic_test /dev/gpioled 1 &
然后紧接着输入LED灯关闭命令:
./gpioled_atomic_test /dev/gpioled 0 &
运行结果如下:
在这里插入图片描述

图 3.2

可以看出和信号量的测试结果一样。
卸载模块命令:
rmmod gpioled_mutex

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值