字元裝置驅動 訊號量

2021-07-29 14:49:23 字數 3125 閱讀 8948

訊號量與自旋鎖的區別:當乙個程序試圖去獲取乙個已經鎖住的訊號量時,程序不會像自旋鎖一樣在原地忙等待。而是會將自身進入乙個等待佇列中睡眠,直到擁有訊號量的程序釋放訊號量後等待佇列中的那個程序才被喚醒。

不能睡眠的程序不能使用訊號量

驅動程式:

/*******************************************

使用linux3.2.81核心

********************************************/

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

static

struct

class *buttonsdrv_class; //類結構體

static

struct device *buttonsdrv_class_dev; //裝置結構體

volatile

unsigned

long *gpfcon = null ;

volatile

unsigned

long *gpfdat = null;

volatile

unsigned

long *gpgcon = null ;

volatile

unsigned

long *gpgdat = null;

unsigned

int press_cnt[4]; //記錄該按鍵按下的次數

static declare_wait_queue_head(button_waitq); //宣告(定義)等待佇列

/* 中斷事件標誌, 中斷服務程式將它置1,buttons_drv_read將它清0 */

static

volatile

int ev_press = 0;

static define_semaphore(button_lock); //定義互斥鎖

//中斷處理函式

static irqreturn_t buttons_irq(int irq, void *dev_id)

static

int buttons_drv_open(struct inode *inode, struct file *file)

else

/*引數解析:中斷號,中斷處理函式,中斷處理標誌(如:雙邊沿觸發),中斷名稱(任意取),

dev_id(中斷處理函式)在中斷共享時會用到,一般設定為這個裝置的裝置結構體或者null

*/request_irq(irq_eint0,buttons_irq, irq_type_edge_both, "s2",&press_cnt[0]); /* 配置gpf0為輸入引腳 ,註冊中斷處理函式*/

request_irq(irq_eint2,buttons_irq, irq_type_edge_both, "s3",&press_cnt[1]);

request_irq(irq_eint11,buttons_irq,irq_type_edge_both, "s4",&press_cnt[2]);

request_irq(irq_eint19,buttons_irq,irq_type_edge_both, "s5",&press_cnt[3]);

return0;}

static

int buttons_drv_close(struct inode *inode, struct file *file)

static

int buttons_drv_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)

else

/* 如果有按鍵動作, 返回鍵值 */

copy_to_user(buf, press_cnt, min(sizeof(press_cnt),size)); //根據實際需要讀出對應個數的值到使用者空間

ev_press = 0; //讀取完後清0

return1;}

/*當應用程式操作裝置檔案時所呼叫的open、read、write等函式,最終會呼叫這個結構體中上的對應函式

*/static

struct file_operations buttons_drv_fops = ;

int major;

//指定insmod命令時會呼叫這個函式

static

int buttons_drv_init(void)

//執行rmmod時會呼叫這個函式

static

void buttons_drv_exit(void)

//指定驅動程式的初始化函式和解除安裝函式

module_init(buttons_drv_init);

module_exit(buttons_drv_exit);

module_license("gpl"); //防止出現「module license」unspecified taints kernel的警告

測試程式(應用程式):

/*

字元裝置測試程式

功能:讀取各個按鍵被按下的次數,驅動使用了訊號量,所以每次只能有乙個程序去獲取鎖

防止併發帶來的異常。並且底層的read驅動函式沒有阻塞,所以應用程式讀取時也不

會阻塞。

*/#include

#include

#include

#include

#include

int fd;

int main(int argc , char ** argv)

while (1)

sleep(5);

}}

字元裝置驅動第八課 訊號量

用於同步,猶如紅綠燈,訊號量為0時則阻塞,訊號量大於0則往下走,可對訊號量進行加減 pv操作 struct semaphore sem 定義訊號量 功能 設定訊號量sem的初始值為val void sema init struct semaphore sem,int val void up stru...

Linux裝置驅動中的併發控制 訊號量

linux 裝置驅動中必須解決的乙個問題是多個程序對共享資源的併發訪問,併發訪問會導致競態。1 併發與競態 併發 concurrency 指的是多個執行單元同時 並行被執行,而併發的執行單元對共享資源 硬體資源和軟體上的全域性變數 靜態變數等 的訪問則很容易導致競態 race conditions ...

訊號量 二值訊號量

訊號量 二值訊號量 訊號量是作業系統的重要部分,訊號量一般用來進行資源管理和任務同步。freertos中訊號量分為二值訊號量 互斥訊號量 計數訊號量和遞迴互斥訊號量,應用場景各不同。二值訊號量通常用於互斥訪問或同步,二值訊號量和互斥訊號量非常相似,但互斥訊號量有優先順序,二值訊號量沒有。因此二值訊號...