文章目錄
- 前言
- 1、spinlock是什么?
- 2、自旋鎖實驗
- 2.1源碼
- 2.2 結果圖
- 總結
前言
本文記錄在rk3568開發板做的自旋鎖實驗。通過自旋鎖控制state變量來限制只有一個應用程序來打開驅動設備。
1、spinlock是什么?
spinlock稱為自旋鎖,如果獲取不到資源,就只能一直傻傻地等待資源被釋放——“原地打轉”,所以稱為自旋鎖。
Linux內核使用結構體spinlock_t表示自旋鎖。
typedef struct spinlock {
union {
struct raw_spinlock rlock;#ifdef CONFIG_DEBUG_LOCK_ALLOC
# define LOCK_PADSIZE (offsetof(struct raw_spinlock, dep_map))
struct {u8 __padding[LOCK_PADSIZE];
struct lockdep_map dep_map;
};
#endif
};
} spinlock_t;
在使用自旋鎖之前,肯定要先定義一個自旋鎖變量,定義方法如下所示:
spinlock_t lock; //定義自旋鎖
自旋鎖API函數
注意:
若線程A執行自旋鎖的過程中,被中斷打斷了,中斷也有執行自旋鎖的操作,那么為了防止死鎖的出現,最好的解決辦法是獲取鎖之前,關閉本地中斷。
線程與中斷并發訪問處理 API 函數
建議使用 spin_lock_irqsave/ spin_unlock_irqrestore,因為這一組函
數會保存中斷狀態,在釋放鎖的時候會恢復中斷狀態。一般在線程中使用 spin_lock_irqsave/
spin_unlock_irqrestore,在中斷中使用 spin_lock/spin_unlock,示例代碼如下所示:
DEFINE_SPINLOCK(lock) /* 定義并初始化一個鎖 *//* 線程 A */
void functionA (){unsigned long flags; /* 中斷狀態 */spin_lock_irqsave(&lock, flags) /* 獲取鎖 *//* 臨界區 */spin_unlock_irqrestore(&lock, flags) /* 釋放鎖 */
}/* 中斷服務函數 */
void irq() {spin_lock(&lock) /* 獲取鎖 *//* 臨界區 */spin_unlock(&lock) /* 釋放鎖 */
}
下半部(BH)也會競爭共享資源,有些資料也會將下半部叫做底半部。關于下半部后面的
章節會講解,如果要在下半部里面使用自旋鎖
2、自旋鎖實驗
本實驗目的:用spinlock的lock變量控制state變量加減,state控制應用程序只允許打開一個。
思路:
- 在驅動程序init初始化lock
- 每次open驅動設備,都會上鎖解鎖來限制state變量,防止其他線程修改state變量。state為1的時候表示有應用程序在占用設備。為0則表示設備空閑。
- 應用程序結束后,state變量減1,表示釋放設備資源。(realse也要用自旋鎖控制state)
2.1源碼
驅動程序:spinlock.c
#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>#define GPIOLED_CNT 1 /* 設備號個數 */
#define GPIOLED_NAME "gpioled" /* 名字 */
#define LEDOFF 0 /* 關燈 */
#define LEDON 1 /* 開燈 */struct led_dev
{dev_t devid; /* 設備號 */struct cdev cdev; /* cdev */struct class *class; /* 類 */struct device *device; /* 設備 */int major;