Linux驅動開發筆記 裝置驅動中的阻塞和同步機制

2021-09-25 04:01:18 字數 3028 閱讀 3765

阻塞呼叫:呼叫結果返回之前,當前執行緒被掛起,函式只有在得到結果之後才會返回

非阻塞呼叫:在不能立即得到結果之前,該函式不會阻塞當前程序,而會立即返回

阻塞程序可以使用等待佇列來實現

等待佇列的基本資料結構是乙個雙向鍊錶,儲存睡眠的程序

等待佇列定義:

struct __wait_queue_head ;

typedef struct __wait_queue_head wait_queue_head_t;

(1)lock

功能:對task_list起保護作用

當要向task_list鍊錶中加入或刪除元素時,核心內部會鎖定lock鎖,當修改完成後,會釋放lock鎖

(2)task_list

雙向鍊錶,存放等待的程序

(1)定義和初始化等待佇列頭

定義:

struct wait_queue_head_t wait;
初始化定義:

#define declare_wait_queue_head(name) \

wait_queue_head_t name = __wait_queue_head_initializer(name)

(2)定義等待佇列

#define declare_waitqueue(name, tsk) \

wait_queue_t name = __waitqueue_initializer(name, tsk)

(3)新增和移除等待佇列

// 將等待佇列元素wait新增到等待佇列頭q所指向的等待佇列鍊錶中

void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);

// 將佇列元素wait從等待佇列頭q所指向的等待佇列鍊錶中移除

void remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);

(4)等待事件

#define wait_event(wq, condition)

#define wait_event_timeout(wq, condition, ret)

#define wait_event_interruptible(wq, condition, ret)

#define wait_event_interruptible_timeout(wq, condition, ret)

(5)喚醒等待佇列

#define wake_up(x)  __wake_up(x, task_normal, 1, null)

#define wake_up_interruptible(x) __wake_up(x, task_interruptible, 1, null)

程序同步機制設計首先需要乙個等待佇列,所有等待乙個事件完成的程序都掛在這個等待佇列中:

struct customevent;
為了實現實驗的意圖,設計兩個指標分別表示事件頭部和尾部:

customevent *lpevent_head = null;  // 鏈頭指標

customevent *lpevent_end = null; // 鏈尾指標

每個事件由乙個鍊錶組成,每個鍊錶中包含了等待這個事件的等待佇列:

findeventnum()從乙個事件鍊錶中找到某乙個事件對應的鍊錶:

// 引數1:事件序號  引數2:返回事件的前乙個事件

customevent *findeventnum(int eventnum, customevent **prev)

*prev = tmp;

tmp=tmp->next;

}return null;

}

系統呼叫函式sys_customevent_open():新分配乙個事件,並返回新分配事件的事件號。

// 建立乙個新的事件  eventnum:事件號

asmlinkage int sys_customevent_open(int eventnum)

else

} else else

return new->eventnum;

}return 0;

}

將程序阻塞到乙個事件的系統呼叫函式,直到等待事件被喚醒時,事件才退出。

// 實現等待佇列系統呼叫

asmlinkage int sys_customevent_wait(int eventnum)

return -1;

}

喚醒等待特定事件函式:

// 喚醒等待事件

asmlinkage int sys_customevent_signal(int eventnum)

wake_up(tmp->p); // 喚醒佇列上所有程序

return 1;

}

關閉事件函式:先喚醒事件上的等待佇列,然後清除事件占用空間

// 喚醒等待事件

asmlinkage int sys_customevent_close(int eventnum)

else if(releaseitem == lpevent_head) else

sys_customevent_signal(eventnum); // 喚醒需要關閉的事件

if(releasenum)

return releaseitem;

}return 0;

}

Linux驅動開發筆記(二)

linux驅動開發的基本框架 define led major 200 define led name led static int led open struct inode inode,struct file filp static int led release struct inode in...

驅動 linux裝置驅動 字元裝置驅動開發

preface 前面對linux裝置驅動的相應知識點進行了總結,現在進入實踐階段!linux 裝置驅動入門篇 linux 裝置驅動掃盲篇 fedora下的字元裝置驅動開發 開發乙個基本的字元裝置驅動 在linux核心驅動中,字元裝置是最基本的裝置驅動。字元裝置包括了裝置最基本的操作,如開啟裝置 關閉...

嵌入式Linux裝置驅動開發筆記(一)

一 linux裝置的分類 字元裝置 塊裝置 網路裝置,三種裝置之間的區別是資料的互動模式,分別為 位元組流 資料塊 資料報。二 vfs核心結構體 vfs核心結構體定義在 linux fs.h 標頭檔案中。1 struct inode結構體 記錄檔案的屬主 訪問時間等資訊。當第一次開啟檔案的時候由vf...