第六章 休眠

2022-07-27 08:33:15 字數 3306 閱讀 8625

在第五章併發與競態中,介紹了乙個當程序需要的資源被其他程序占用,而不得不等待該資源的情形。這裡,要說的則是即便程序得到資源之後,由於資源本身的一些問題而不能預期的完成功能,必須休眠一段時間,直到它的要求得到滿足。兩種情形的區別是顯而易見的,不過在使用上,實在是有點相似。其實最近學的一些東西都是這樣,訊號量,自旋鎖

....

不管他們的內在區別的話,使用時無外乎就是初始化,然後在乙個地方申請,另乙個地方反饋。

先對休眠有乙個基礎的認識先。就是說,程序確實是在執行,需要的東西也有給它了,但是,給它的東西卻不滿足它的要求,於是乎它還是做不了事。怎麼辦呢,就只有讓它等了,當前程序也就休眠了。進入休眠的時候會把它對資源的要求提出來,一旦這個要求得到滿足,休眠的程序就會立刻被喚醒。

然後是關於休眠的兩個需要注意的地方。首先,進入休眠之後,當前程序就算是失去了對作業系統的控制,休眠多久是不確定的,所以肯定不能放在原子上下文。寧外,之前也強調過的,在使用自旋鎖時一定不能休眠,而訊號量方法是允許休眠的。第二個就是在休眠被喚醒時,程式一定要再次檢查要求是否得到滿足,這個一點都不多餘。

作業系統的知識告訴我,以上說的起始就是程序的阻塞了。作業系統會有乙個等待佇列來管理阻塞的程序,要實現休眠的第一步也就是構建乙個等待佇列頭了。如下:

1

declare_wait_queue_head(name);

//靜態

2wait_queue_head_t my_queue;

3init_waitqueue_head(

&my_queue);

//動態

下面的方法讓程序進入休眠:

1

wait_event(queue, condition)

2wait_event_interruptible(queue, condition)

//可中斷

3wait_event_timeout(queue, condition, timeout)

4wait_event_interruptible_timeout(queue, condition, timeout)

condition

也就是程序提出的要求了,這是乙個布林表示式,當表示式為真時,休眠的程序就會立刻被喚醒。

喚醒用以下函式,這個就沒什麼好講的了

:

1

void

wake_up(wait_queue_head_t

*queue);

2void

wake_up_interruptible(wait_queue_head_t

*queue);

之前的scull

專案本身是沒有支援休眠的,但是

scull

原始碼下的

pipe

.c檔案給我們提供了乙個休眠的例項。這是驅動程式跟之前的scull

很是不同,它用到了緩衝區來讀寫資料。這樣才會出現讀寫時阻塞的情況。讀資料時緩衝區為空阻塞,寫資料時緩衝區已滿阻塞。

scullpiep

的裝置結構如下:

1

struct

scull_pipe ;

讀取的**如下:

1

static

ssize_t scull_p_read (

struct

file

*filp,

char

__user

*buf, size_t count,

2loff_t

*f_pos)320

/*ok, data is there, return something

*/21

if(dev

->

wp >

dev->

rp)22

count

=min(count, (size_t)(dev

->

wp -

dev->

rp));

23else

/**/

24count

=min(count, (size_t)(dev

->

end

-dev

->

rp));

25if

(copy_to_user(buf, dev

->

rp, count))

29dev

->

rp +=

count;

30if

(dev

->

rp ==

dev->

end)

31dev

->

rp =

dev->

buffer;

/**/

32up (

&dev

->

sem);

3334

/*finally, awake any writers and return

*/35

wake_up_interruptible(

&dev

->

outq);

36pdebug(

"\"%s\" did read %li bytes\n

",current

->

comm, (

long

)count);

37return

count;

38}

迴圈的內容。

dev->rp == dev->wp

表示緩衝區為空,這時程序不能順利的讀資料,必須休眠。因為這裡使用了訊號量來管理併發程序,當前程序休眠時必須先釋放訊號量,以便其他程序執行。

wait_event_interruptible(dev->inq, (dev->rp != dev->wp))

就是進入休眠了,被喚醒之後,就接著執行之後的**,第一步也就是重新獲取訊號量了。這裡也並沒有直接退出

while

迴圈,迴圈條件仍需要判斷,之前就說過,這個對要求是否得到滿足的再次判斷是不多餘的。後面的一些讀取操作以前的沒太大區別。

接下來的重點就在於在**喚醒這個休眠中的程序了。其實很簡單,在write

方法完成的時候,執行以下**就行了

:

1

*finally

, awake any reader */2

wake_up_interruptible(

&dev

->

inq);

/*blocked in read() and select()

*/

mysql第六章 第六章 mysql日誌

第六章 mysql日誌 一 錯誤日誌 錯誤日誌的預設存放路徑是 mysql 存放資料的地方 hostname.err 1.修改錯誤日誌存放路徑 mysqld log error data mysql mysql.log 2.檢視配置命令 show variables like log error 3...

第六章 指標

1.多位元組資料的位址是在最左邊還是最右邊的位置,不同的機器有不同的規定,這也正是大端和小端的區別,位址也要遵從邊界對齊 2.高階語言的乙個特性就是通過名字而不是位址來訪問記憶體的位置,但是硬體仍然通過位址訪問記憶體位置 3.記憶體中的變數都是義序列的0或1的位,他們可以被解釋為整數或者其他,這取決...

第六章總結

6.1 使用滑鼠 6.1.1 滑鼠時間和滑鼠訊息 根據使用者操作滑鼠時滑鼠的位置,滑鼠訊息分為兩類 客戶區滑鼠訊息和非客戶區滑鼠訊息。1.客戶去滑鼠訊息 2.當滑鼠游標位於視窗的使用者區時,將生成客戶滑鼠訊息。滑鼠訊息和鍵盤訊息有所不同,windows 只將鍵盤有訊息傳送給具有輸入極點的視窗,但滑鼠...