freepeople性欧美熟妇, 色戒完整版无删减158分钟hd, 无码精品国产vα在线观看DVD, 丰满少妇伦精品无码专区在线观看,艾栗栗与纹身男宾馆3p50分钟,国产AV片在线观看,黑人与美女高潮,18岁女RAPPERDISSSUBS,国产手机在机看影片

正文內(nèi)容

高級(jí)字符驅(qū)動(dòng)操作說(shuō)明(文件)

 

【正文】 出命令的程序甚至常常不需要運(yùn)行在和它要控制的設(shè)備所在的同一個(gè)系統(tǒng)上.例如, setterm 程序作用于控制臺(tái)(或者其他終端)配置, 通過(guò)打印 escape 序列. 控制程序可位于和被控制的設(shè)備不同的一臺(tái)計(jì)算機(jī)上, 因?yàn)橐粋€(gè)簡(jiǎn)單的數(shù)據(jù)流重定向可完成這個(gè)配置工作. 這是每次你運(yùn)行一個(gè)遠(yuǎn)程 tty 會(huì)話(huà)時(shí)所發(fā)生的事情: escape 序列在遠(yuǎn)端被打印但是影響到本地的 tty。阻塞 I/O回顧第 3 章, 我們看到如何實(shí)現(xiàn) read 和 write 方法. 在此, 但是, 我們跳過(guò)了一個(gè)重要的問(wèn)題:一個(gè)驅(qū)動(dòng)當(dāng)它無(wú)法立刻滿(mǎn)足請(qǐng)求應(yīng)當(dāng)如何響應(yīng)? 一個(gè)對(duì) read 的調(diào)用可能當(dāng)沒(méi)有數(shù)據(jù)時(shí)到來(lái), 而以后會(huì)期待更多的數(shù)據(jù). 或者一個(gè)進(jìn)程可能試圖寫(xiě), 但是你的設(shè)備沒(méi)有準(zhǔn)備好接受數(shù)據(jù), 因?yàn)槟愕妮敵鼍彌_滿(mǎn)了. 調(diào)用進(jìn)程往往不關(guān)心這種問(wèn)題。 那個(gè)進(jìn)程可能在你之前醒來(lái)并且獲取了你在等待的資源. 結(jié)果是你不能關(guān)于你醒后的系統(tǒng)狀態(tài)做任何的假設(shè), 并且你必須檢查來(lái)確保你在等待的條件是, 確實(shí), 真的.一個(gè)另外的相關(guān)的點(diǎn), 當(dāng)然, 是你的進(jìn)程不能睡眠除非確信其他人, 在某處的, 將喚醒它. 做喚醒工作的代碼必須也能夠找到你的進(jìn)程來(lái)做它的工作. 確保一個(gè)喚醒發(fā)生, 是深入考慮你的代碼和對(duì)于每次睡眠, 確切知道什么系列的事件將結(jié)束那次睡眠. 使你的進(jìn)程可能被找到, 真正地, 通過(guò)一個(gè)稱(chēng)為等待隊(duì)列的數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)的. 一個(gè)等待隊(duì)列就是它聽(tīng)起來(lái)的樣子:一個(gè)進(jìn)程列表, 都等待一個(gè)特定的事件.在 Linux 中, 一個(gè)等待隊(duì)列由一個(gè)等待隊(duì)列頭來(lái)管理, 一個(gè) wait_queue_head_t 類(lèi)型的結(jié)構(gòu), 定義在linux/中. 一個(gè)等待隊(duì)列頭可被定義和初始化, 使用:DECLARE_WAIT_QUEUE_HEAD(name)。我們將很快返回到等待隊(duì)列結(jié)構(gòu), 但是我們知道了足夠多的來(lái)首先看看睡眠和喚醒.. 一個(gè)非零值意味著你的睡眠被某些信號(hào)打斷, 并且你的驅(qū)動(dòng)可能應(yīng)當(dāng)返回 ERESTARTSYS. 最后的版本(wait_event_timeout 和 wait_event_interruptible_timeout)等待一段有限的時(shí)間。 實(shí)際上, 慣例是使用 wake_up 如果你在使用 wait_event , wake_up_interruptible 如果你在使用 wait_event_interruptible.我們現(xiàn)在知道足夠多來(lái)看一個(gè)簡(jiǎn)單的睡眠和喚醒的例子. 在這個(gè)例子代碼中, 你可找到一個(gè)稱(chēng)為 sleepy 的模塊. 它實(shí)現(xiàn)一個(gè)有簡(jiǎn)單行為的設(shè)備:任何試圖從這個(gè)設(shè)備讀取的進(jìn)程都被置為睡眠. 無(wú)論何時(shí)一個(gè)進(jìn)程寫(xiě)這個(gè)設(shè)備, 所有的睡眠進(jìn)程被喚醒. 這個(gè)行為由下面的 read 和 write 方法實(shí)現(xiàn):static DECLARE_WAIT_QUEUE_HEAD(wq)。 flag = 0。 flag = 1。 /* succeed, to avoid retrial */}注意這個(gè)例子里 flag 變量的使用. 因?yàn)?wait_event_interruptible 檢查一個(gè)必須變?yōu)檎娴臈l件, 我們使用 flag 來(lái)創(chuàng)建那個(gè)條件.有趣的是考慮當(dāng) sleepy_write 被調(diào)用時(shí)如果有 2 個(gè)進(jìn)程在等待會(huì)發(fā)生什么. 因?yàn)?sleepy_read 重置 flag 為 0 一旦它醒來(lái), 你可能認(rèn)為醒來(lái)的第 2 個(gè)進(jìn)程會(huì)立刻回到睡眠. 在一個(gè)單處理器系統(tǒng), 這幾乎一直是發(fā)生的事情. 但是重要的是要理解為什么你不能依賴(lài)這個(gè)行為. wake_up_interruptible 調(diào)用將使 2 個(gè)睡眠進(jìn)程醒來(lái). 完全可能它們都注意到 flag 是非零, 在另一個(gè)有機(jī)會(huì)重置它之前. 對(duì)于這個(gè)小模塊, 這個(gè)競(jìng)爭(zhēng)條件是不重要的. 在一個(gè)真實(shí)的驅(qū)動(dòng)中, 這種競(jìng)爭(zhēng)可能導(dǎo)致少見(jiàn)的難于查找的崩潰. 如果正確的操作要求只能有一個(gè)進(jìn)程看到這個(gè)非零值, 它將必須以原子的方式被測(cè)試. 我們將見(jiàn)到一個(gè)真正的驅(qū)動(dòng)如何處理這樣的情況. 但首先我們必須開(kāi)始另一個(gè)主題.. 如果一個(gè)進(jìn)程調(diào)用 write 并且在緩沖中沒(méi)有空間, 這個(gè)進(jìn)程必須阻塞, 并且它必須在一個(gè)與用作 read 的不同的等待隊(duì)列中. 當(dāng)一些數(shù)據(jù)被寫(xiě)入硬件設(shè)備, 并且在輸出緩沖中的空間變空閑, 這個(gè)進(jìn)程被喚醒并且寫(xiě)調(diào)用成功, 盡管數(shù)據(jù)可能只被部分寫(xiě)入如果在緩沖只沒(méi)有空間給被請(qǐng)求的 count 字節(jié).這 2 句都假定有輸入和輸出緩沖。 例如, 一個(gè)磁帶設(shè)備的 open 常常阻塞直到插入一個(gè)磁帶. 如果這個(gè)磁帶驅(qū)動(dòng)器使用 O_NONBLOCK 打開(kāi), 這個(gè) open 立刻成功, 不管是否介質(zhì)在或不在.只有 read, write, 和 open 文件操作受到非阻塞標(biāo)志影響.. 類(lèi)似地, 讀進(jìn)程被用來(lái)喚醒正在等待緩沖空間可用的寫(xiě)者進(jìn)程.這個(gè)設(shè)備驅(qū)動(dòng)使用一個(gè)設(shè)備結(jié)構(gòu), 它包含 2 個(gè)等待隊(duì)列和一個(gè)緩沖. 緩沖大小是以常用的方法可配置的(在編譯時(shí)間, 加載時(shí)間, 或者運(yùn)行時(shí)間).struct scull_pipe{ wait_queue_head_t inq, outq。 /* where to read, where to write */ int nreaders, nwriters。 /* Char device structure */}。 while (devrp == devwp) { /* nothing to read */ up(amp。 PDEBUG(\%s\ reading: going to sleep\n, currentm)。 } /* ok, data is there, return something */ if (devwp devrp) count = min(count, (size_t)(devwp devrp))。 return EFAULT。devsem)。 return count。 只有這時(shí)我們才可以測(cè)試讀緩沖(在 while 循環(huán)中)并且真正知道我們可以返回緩沖中的數(shù)據(jù)給用戶(hù). 全部這個(gè)代碼的最終結(jié)果是, 當(dāng)我們從 while 循環(huán)中退出時(shí), 我們知道旗標(biāo)被獲得并且緩沖中有數(shù)據(jù)我們可以用.僅僅為了完整, 我們要注意, scull_p_read 可以在另一個(gè)地方睡眠, 在我們獲得設(shè)備旗標(biāo)之后: 對(duì) copy_to_user 的調(diào)用. 如果 scull 當(dāng)在內(nèi)核和用戶(hù)空間之間拷貝數(shù)據(jù)時(shí)睡眠, 它在持有設(shè)備旗標(biāo)中睡眠. 在這種情況下持有旗標(biāo)是合理的因?yàn)樗荒芩梨i系統(tǒng)(我們知道內(nèi)核將進(jìn)行拷貝到用戶(hù)空間并且在不加鎖進(jìn)程中的同一個(gè)旗標(biāo)下喚醒我們), 并且因?yàn)橹匾氖窃O(shè)備內(nèi)存數(shù)組在驅(qū)動(dòng)睡眠時(shí)不改變.. 當(dāng)然, 它們對(duì)應(yīng) 2 類(lèi)的睡眠. 其他的狀態(tài)正常地和驅(qū)動(dòng)編寫(xiě)者無(wú)關(guān).在 內(nèi)核, 對(duì)于驅(qū)動(dòng)代碼通常不需要直接操作進(jìn)程狀態(tài). 但是, 如果你需要這樣做, 使用的代碼是:void set_current_state(int new_state)。 如果在你忙于上面的這個(gè)過(guò)程并且有其他的線(xiàn)程剛剛試圖喚醒你, 如果這個(gè)條件變?yōu)檎鏁?huì)發(fā)生什么? 你可能錯(cuò)過(guò)喚醒并且睡眠超過(guò)你預(yù)想的時(shí)間. 因此, 在睡眠的代碼下面, 典型地你會(huì)見(jiàn)到下面的代碼:if (!condition) schedule()。 linux/ 包含了所有需要的定義, 以及圍繞例子的內(nèi)核源碼. 但是, 有一個(gè)更容易的方式.第一步是創(chuàng)建和初始化一個(gè)等待隊(duì)列. 這常常由這個(gè)宏定義完成:DEFINE_WAIT(my_wait)。但是常常更容易的做法是放一個(gè) DEFINE_WAIT 行在循環(huán)的頂部, 來(lái)實(shí)現(xiàn)你的睡眠.下一步是添加你的等待隊(duì)列入口到隊(duì)列, 并且設(shè)置進(jìn)程狀態(tài). 2 個(gè)任務(wù)都由這個(gè)函數(shù)處理:void prepare_to_wait(wait_queue_head_t *queue, wait_queue_t *wait, int state)。 return ((devrp + devbuffersize devwp) % devbuffersize) 1。devsem)) return ERESTARTSYS。 /* scull_getwritespace called up(amp。 PDEBUG(Going to accept %li bytes to %p from %p\n, (long)count, devwp, buf)。 } devwp += count。 /* finally, awake any reader */ wake_up_interruptible(amp。 PDEBUG(\%s\ did write %li bytes\n,currentm, (long)count)。 up(amp。 PDEBUG(\%s\ writing: going to sleep\n,currentm)。 if (spacefree(dev) == 0) schedule()。 if (signal_pending(current)) return ERESTARTSYS。}再次注意 while 循環(huán). 如果有空間可用而不必睡眠, 這個(gè)函數(shù)簡(jiǎn)單地返回. 否則, 它必須丟掉設(shè)備旗標(biāo)并且等待. 這個(gè)代碼使用 DEFINE。devsem)) return ERESTARTSYS。devoutq, amp。devoutq, amp。 if (filpf_flags amp。}這個(gè)代碼看來(lái)和 read 方法類(lèi)似, 除了我們已經(jīng)將睡眠代碼放到了一個(gè)單獨(dú)的函數(shù), 稱(chēng)為 scull_getwritespace. 它的工作是確保在緩沖中有空間給新的數(shù)據(jù), 睡眠直到有空間可用. 一旦空間在, scull_p_write 可簡(jiǎn)單地拷貝用戶(hù)的數(shù)據(jù)到那里, 調(diào)整指針, 并且喚醒可能已經(jīng)在等待讀取數(shù)據(jù)的進(jìn)程.處理實(shí)際的睡眠的代碼是:/* Wait for space for writing。 /* blocked in read() and select() */ /* and signal asynchronous readers, explained late in chapter 5 */ if (devasync_queue) kill_fasync(amp。 /* wrapped */ up(amp。devsem)。 if (devwp = devrp) count = min(count, (size_t)(devend devwp))。s space to write */ result = scull_getwritespace(dev, filp)。 int result。 它應(yīng)當(dāng)或者是 TASK_INTERRUPTIBLE(給可中斷的睡眠, 這常常是你所要的)或者 TASK_UNINTERRUPTIBLE(給不可中斷睡眠).在調(diào)用 prepare_to_wait 之后, 進(jìn)程可調(diào)用 schedule 在它已檢查確認(rèn)它仍然需要等待之后. 一旦 schedule 返回, 就到了清理時(shí)間. 這個(gè)任務(wù), 也, 被一個(gè)特殊的函數(shù)處理:void finish_wait(wait_queue_head_t *queue, wait_queue_t *wait)。init_wait(amp。 那個(gè)函數(shù)不會(huì)返回直到進(jìn)程處于可運(yùn)行態(tài). 如果由于不再需要睡眠而對(duì) schedule 的調(diào)用被跳過(guò), 進(jìn)程狀態(tài)將不正確. 還有必要從等待隊(duì)列中去除這個(gè)進(jìn)程, 否則它可能被多次喚醒.. 但是象這樣直接改變 current 是不鼓勵(lì)的。一個(gè)進(jìn)程如何睡眠如果我們深入 linux/, 你見(jiàn)到在 wait_queue_head_t 類(lèi)型后面的數(shù)據(jù)結(jié)構(gòu)是非常簡(jiǎn)單的。 如果我們要持有它而睡眠, 就不會(huì)有寫(xiě)者有機(jī)會(huì)喚醒我們. 一旦這個(gè)確保被丟掉, 我們做一個(gè)快速檢查來(lái)看是否用戶(hù)已請(qǐng)求非阻塞 I/O, 并且如果是這樣就返回. 否則, 是時(shí)間調(diào)用 wait_event_interruptible.一旦我們過(guò)了這個(gè)調(diào)用, 某些東東已經(jīng)喚醒了我們, 但是我們不知道是什么. 一個(gè)可能是進(jìn)程接收到了一個(gè)信號(hào). 包含 wait_event_interruptible 調(diào)用的這個(gè) if 語(yǔ)句檢查這種情況. 這個(gè)語(yǔ)句保證了正確的和被期望的對(duì)信號(hào)的反應(yīng), 它可能負(fù)責(zé)喚醒這個(gè)進(jìn)程(因?yàn)槲覀兲幱谝粋€(gè)可中斷的睡眠). 如果一個(gè)信號(hào)已經(jīng)到達(dá)并且它沒(méi)有被這個(gè)進(jìn)程阻塞, 正確的做法是讓內(nèi)核的上層處理這個(gè)事件. 到此, 這個(gè)驅(qū)動(dòng)返回 ERESTARTSYS 到調(diào)用者。devoutq)。 if (devrp == devend) devrp = devbuffer。 if (copy_to_user(buf, devrp, count)) {
點(diǎn)擊復(fù)制文檔內(nèi)容
公司管理相關(guān)推薦
文庫(kù)吧 www.dybbs8.com
備案圖鄂ICP備17016276號(hào)-1