今天寫的是linux裝置驅動中的阻塞和非阻塞i/0,何謂阻塞與非阻塞i/o?簡單來說就是對i/o操作的兩種不同的方式,驅動程式可以靈活的支援使用者空間對裝置的這兩種訪問方式。
一、基本概念:
二、輪詢操作
阻塞的讀取乙個字元:
1
2
3
4
5
6
7
8
char
buf;
fd = open(
"/dev/ttys1"
,o_rdwr);
.....
res = read(fd,&buf,1);
//當串列埠上有輸入時才返回,沒有輸入則程序掛起睡眠
if
(res == 1)
非阻塞的讀乙個字元:
1
2
3
4
5
char
buf;
fd = open(
"/dev/ttys1"
,o_rdwr|o_nonblock);
//o_nonblock 非阻塞標識
.....
while
(read(fd,&buf,1)!=1);
//串列埠上沒有輸入則返回,所以迴圈讀取
printf
(
"%c/n"
,buf);
阻塞操作常常用等待佇列來實現,而非阻塞操作用輪詢的方式來實現。非阻塞i/o的操作在應用層通常會用到select()和poll()系統呼叫查詢是否可對裝置進行無阻塞訪問。select()和poll()系統呼叫最終會引發裝置驅動中的poll()函式被呼叫。這裡對佇列就不多介紹了,大家可以看看資料結構裡面的知識點。
應用層的select()原型為:
1
2
3
int
select(
int
numfds,fd_set *readfds,fd_set *writefds,fd_set *exceptionfds,
struct
timeval *timeout); numfds 的值為需要檢查的號碼最高的檔案描述符加1,若select()在等待timeout時間後,若沒有檔案描述符準備好則返回。
應用程式為:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#inlcude------
main()
while
(1)
}
}
下面說說裝置驅動中的poll()函式,函式原型如下:
1
static
unsigned
int
poll(
struct
file *file,
struct
socket *sock,poll_table *wait)
//第乙個引數是file結構體指標,第三個引數是輪詢表指標,這個函式應該進行兩項工作
這裡還要提到poll_wait()函式,很多人會以為是和wait_event()一樣的函式,會阻塞的等待某件事情的發生,其實這個函式並不會引起阻塞,它的工作是把當前的程序增添到wait引數指定的等待列表poll_table中去,poll_wait()函式原型如下:
1
2
static
inline
void
poll_wait(
struct
file * filp, wait_queue_head_t * wait_address, poll_table *p)
從中可以看出是將等待佇列頭wait_address新增到p所指向的結構體中(poll_table)
驅動函式中的poll()函式典型模板如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
static
unsigned
int
***_poll(
struct
file *filp,
struct
socket *sock,
poll_table *wait)
三、支援輪詢操作的globalfifo驅動
在globalfifo的poll()函式中,首先將裝置結構體重的r_wait和w_wait等待佇列頭加到等待隊列表,globalfifo裝置驅動的poll()函式如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
static
unsigned
int
gloablfif0_poll(
struct
file *filp,poll_table *wait)
if
(dev->current_len != globalfifo_size)
up(&dev->sem);
return
mask;
}
四、總結
阻塞與非阻塞操作:
poll機制:
深入淺出Linux裝置驅動之字元裝置驅動程式
linux下的裝置驅動程式被組織為一組完成不同任務的函式的集合,通過這些函式使得windows的裝置操作猶如檔案一般。在應用程式看來,硬體裝置只是乙個裝置檔案,應用程式可以象操作普通檔案一樣對硬體裝置進行操作,如open close read write 等。linux主要將裝置分為二類 字元裝置和...
深入淺出 Linux裝置驅動中斷處理介紹
深入淺出 linux裝置驅動中斷處理介紹 與linux裝置驅動中中斷處理相關的首先是申請與釋放irq的api request irq 和free irq request irq 的原型為 int request irq unsigned int irq,void handler int irq,vo...
深入淺出Linux裝置驅動之併發控制
在驅動程式中,當多個執行緒同時訪問相同的資源時 驅動程式中的全域性變數是一種典型的共享資源 可能會引發 競態 因此我們必須對共享資源進行併發控制。linux核心中解決併發控制的最常用方法是自旋鎖與訊號量 絕大多數時候作為互斥鎖使用 自旋鎖與訊號量 類似而不類 類似說的是它們功能上的相似性,不類 指代...