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

正文內(nèi)容

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

2025-04-21 04:29本頁(yè)面
  

【正文】 }再次注意 while 循環(huán). 如果有空間可用而不必睡眠, 這個(gè)函數(shù)簡(jiǎn)單地返回. 否則, 它必須丟掉設(shè)備旗標(biāo)并且等待. 這個(gè)代碼使用 DEFINE。devsem)) return ERESTARTSYS。 if (signal_pending(current)) return ERESTARTSYS。devoutq, amp。 if (spacefree(dev) == 0) schedule()。devoutq, amp。 PDEBUG(\%s\ writing: going to sleep\n,currentm)。 if (filpf_flags amp。 up(amp。}這個(gè)代碼看來(lái)和 read 方法類似, 除了我們已經(jīng)將睡眠代碼放到了一個(gè)單獨(dú)的函數(shù), 稱為 scull_getwritespace. 它的工作是確保在緩沖中有空間給新的數(shù)據(jù), 睡眠直到有空間可用. 一旦空間在, scull_p_write 可簡(jiǎn)單地拷貝用戶的數(shù)據(jù)到那里, 調(diào)整指針, 并且喚醒可能已經(jīng)在等待讀取數(shù)據(jù)的進(jìn)程.處理實(shí)際的睡眠的代碼是:/* Wait for space for writing。 PDEBUG(\%s\ did write %li bytes\n,currentm, (long)count)。 /* blocked in read() and select() */ /* and signal asynchronous readers, explained late in chapter 5 */ if (devasync_queue) kill_fasync(amp。 /* finally, awake any reader */ wake_up_interruptible(amp。 /* wrapped */ up(amp。 } devwp += count。devsem)。 PDEBUG(Going to accept %li bytes to %p from %p\n, (long)count, devwp, buf)。 if (devwp = devrp) count = min(count, (size_t)(devend devwp))。 /* scull_getwritespace called up(amp。s space to write */ result = scull_getwritespace(dev, filp)。devsem)) return ERESTARTSYS。 int result。 return ((devrp + devbuffersize devwp) % devbuffersize) 1。 它應(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)。但是常常更容易的做法是放一個(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)。init_wait(amp。 linux/ 包含了所有需要的定義, 以及圍繞例子的內(nèi)核源碼. 但是, 有一個(gè)更容易的方式.第一步是創(chuàng)建和初始化一個(gè)等待隊(duì)列. 這常常由這個(gè)宏定義完成:DEFINE_WAIT(my_wait)。 那個(gè)函數(shù)不會(huì)返回直到進(jìn)程處于可運(yùn)行態(tài). 如果由于不再需要睡眠而對(duì) schedule 的調(diào)用被跳過(guò), 進(jìn)程狀態(tài)將不正確. 還有必要從等待隊(duì)列中去除這個(gè)進(jìn)程, 否則它可能被多次喚醒.. 如果在你忙于上面的這個(gè)過(guò)程并且有其他的線程剛剛試圖喚醒你, 如果這個(gè)條件變?yōu)檎鏁?huì)發(fā)生什么? 你可能錯(cuò)過(guò)喚醒并且睡眠超過(guò)你預(yù)想的時(shí)間. 因此, 在睡眠的代碼下面, 典型地你會(huì)見到下面的代碼:if (!condition) schedule()。 但是象這樣直接改變 current 是不鼓勵(lì)的。 當(dāng)然, 它們對(duì)應(yīng) 2 類的睡眠. 其他的狀態(tài)正常地和驅(qū)動(dòng)編寫者無(wú)關(guān).在 內(nèi)核, 對(duì)于驅(qū)動(dòng)代碼通常不需要直接操作進(jìn)程狀態(tài). 但是, 如果你需要這樣做, 使用的代碼是:void set_current_state(int new_state)。一個(gè)進(jìn)程如何睡眠如果我們深入 linux/, 你見到在 wait_queue_head_t 類型后面的數(shù)據(jù)結(jié)構(gòu)是非常簡(jiǎn)單的。 只有這時(shí)我們才可以測(cè)試讀緩沖(在 while 循環(huán)中)并且真正知道我們可以返回緩沖中的數(shù)據(jù)給用戶. 全部這個(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)核和用戶空間之間拷貝數(shù)據(jù)時(shí)睡眠, 它在持有設(shè)備旗標(biāo)中睡眠. 在這種情況下持有旗標(biāo)是合理的因?yàn)樗荒芩梨i系統(tǒng)(我們知道內(nèi)核將進(jìn)行拷貝到用戶空間并且在不加鎖進(jìn)程中的同一個(gè)旗標(biāo)下喚醒我們), 并且因?yàn)橹匾氖窃O(shè)備內(nèi)存數(shù)組在驅(qū)動(dòng)睡眠時(shí)不改變.. 如果我們要持有它而睡眠, 就不會(huì)有寫者有機(jī)會(huì)喚醒我們. 一旦這個(gè)確保被丟掉, 我們做一個(gè)快速檢查來(lái)看是否用戶已請(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)用者。 return count。devoutq)。devsem)。 if (devrp == devend) devrp = devbuffer。 return EFAULT。 if (copy_to_user(buf, devrp, count)) { up (amp。 } /* ok, data is there, return something */ if (devwp devrp) count = min(count, (size_t)(devwp devrp))。 /* signal: tell the fs layer to handle it */ /* otherwise loop, but first reacquire the lock */ if (down_interruptible(amp。 PDEBUG(\%s\ reading: going to sleep\n, currentm)。 /* release the lock */ if (filpf_flags amp。 while (devrp == devwp) { /* nothing to read */ up(amp。 if (down_interruptible(amp。 /* Char device structure */}。 /* asynchronous readers */ struct semaphore sem。 /* where to read, where to write */ int nreaders, nwriters。 /* begin of buf, end of buf */ int buffersize。 類似地, 讀進(jìn)程被用來(lái)喚醒正在等待緩沖空間可用的寫者進(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。 它是 scull 的一個(gè)特殊形式, 實(shí)現(xiàn)了一個(gè)象管道的設(shè)備.在驅(qū)動(dòng)中, 一個(gè)阻塞在讀調(diào)用上的進(jìn)程被喚醒, 當(dāng)數(shù)據(jù)到達(dá)時(shí)。 例如, 一個(gè)磁帶設(shè)備的 open 常常阻塞直到插入一個(gè)磁帶. 如果這個(gè)磁帶驅(qū)動(dòng)器使用 O_NONBLOCK 打開, 這個(gè) open 立刻成功, 不管是否介質(zhì)在或不在.只有 read, write, 和 open 文件操作受到非阻塞標(biāo)志影響.. 這個(gè)調(diào)用阻塞并且循環(huán)繼續(xù). 增加一個(gè)輸出緩沖可允許驅(qū)動(dòng)在每個(gè)寫調(diào)用中接收大的數(shù)據(jù)塊, 性能上有相應(yīng)的提高. 如果這個(gè)緩沖足夠大, 寫調(diào)用在第一次嘗試就成功 被緩沖的數(shù)據(jù)之后將被推到設(shè)備 不必控制需要返回用戶空間來(lái)第二次或者第三次寫調(diào)用. 選擇一個(gè)合適的值給輸出緩沖顯然是設(shè)備特定的.我們不使用一個(gè)輸入緩沖在 scull中, 因?yàn)閿?shù)據(jù)當(dāng)發(fā)出 read 時(shí)已經(jīng)可用. 類似的, 不用輸出緩沖, 因?yàn)閿?shù)據(jù)被簡(jiǎn)單地拷貝到和設(shè)備關(guān)聯(lián)的內(nèi)存區(qū). 本質(zhì)上, 這個(gè)設(shè)備是一個(gè)緩沖, 因此額外緩沖的實(shí)現(xiàn)可能是多余的. 我們將在第 10 章見到緩沖的使用.如果指定 O_NONBLOCK, read 和 write 的行為是不同的. 在這個(gè)情況下, 這個(gè)調(diào)用簡(jiǎn)單地返回 EAGAIN((try it agin)如果一個(gè)進(jìn)程當(dāng)沒(méi)有數(shù)據(jù)可用時(shí)調(diào)用 read , 或者如果當(dāng)緩沖中沒(méi)有空間時(shí)它調(diào)用 write .如你可能期望的, 非阻塞操作立刻返回, 允許這個(gè)應(yīng)用程序輪詢數(shù)據(jù). 應(yīng)用程序當(dāng)使用 stdio 函數(shù)處理非阻塞文件中, 必須小心, 因?yàn)樗鼈內(nèi)菀赘沐e(cuò)一個(gè)的非阻塞返回為 EOF. 它們始終必須檢查 errno.自然地, O_NONBLOCK 也在 open 方法中有意義. 這個(gè)發(fā)生在當(dāng)這個(gè)調(diào)用真正阻塞長(zhǎng)時(shí)間時(shí)。 如果一個(gè)進(jìn)程調(diào)用 write 并且在緩沖中沒(méi)有空間, 這個(gè)進(jìn)程必須阻塞, 并且它必須在一個(gè)與用作 read 的不同的等待隊(duì)列中. 當(dāng)一些數(shù)據(jù)被寫入硬件設(shè)備, 并且在輸出緩沖中的空間變空閑, 這個(gè)進(jìn)程被喚醒并且寫調(diào)用成功, 盡管數(shù)據(jù)可能只被部分寫入如果在緩沖只沒(méi)有空間給被請(qǐng)求的 count 字節(jié).這 2 句都假定有輸入和輸出緩沖。 這是一個(gè)替代 O_NONBLOCK 的名子, 為兼容 System V 代碼而被接受的. 這個(gè)標(biāo)志缺省地被清除, 因?yàn)橐粋€(gè)等待數(shù)據(jù)的進(jìn)程的正常行為僅僅是睡眠. 在一個(gè)阻塞操作的情況下, 這是缺省地, 下列的行為應(yīng)當(dāng)實(shí)現(xiàn)來(lái)符合標(biāo)準(zhǔn)語(yǔ)法: /* 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ā)生的事情. 但是重要的是要理解為什么你不能依賴這個(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)致少見的難于查找的崩潰. 如果正確的操作要求只能有一個(gè)進(jìn)程看到這個(gè)非零值, 它將必須以原子的方式被測(cè)試. 我們將見到一個(gè)真正的驅(qū)動(dòng)如何處理這樣的情況. 但首先我們必須開始另一個(gè)主題..wq)。 flag = 1。 return 0。 flag = 0。ssize_t sleepy_read (struct file *filp, char __user *buf, size_t coun
點(diǎn)擊復(fù)制文檔內(nèi)容
公司管理相關(guān)推薦
文庫(kù)吧 www.dybbs8.com
備案圖鄂ICP備17016276號(hào)-1