i.MX6ULL終結者Linux併發與競爭實驗互斥體實驗
技術標籤:i.MX6ULL終結者# 第四部分 Linux驅動開發嵌入式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所示:
驅動模組載入成功後,使用gpioled_atomic_test應用測試程式進行測試,測試流程和原子變數測試一樣。使用下面的命令開啟LED燈:
./gpioled_atomic_test /dev/gpioled 1 &
然後緊接著輸入LED燈關閉命令:
./gpioled_atomic_test /dev/gpioled 0 &
執行結果如下:
可以看出和訊號量的測試結果一樣。
解除安裝模組命令:
rmmod gpioled_mutex