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

正文內(nèi)容

高級字符驅(qū)動操作說明-資料下載頁

2025-04-18 04:29本頁面
  

【正文】 它或者重啟系統(tǒng)調(diào)用或者返回 EINTR 給用戶空間. 我們使用相同類型的檢查來處理信號, 給每個讀和寫實現(xiàn).但是, 即便沒有一個信號, 我們還是不確切知道有數(shù)據(jù)在那里為獲取. 其他人也可能已經(jīng)在等待數(shù)據(jù), 并且它們可能贏得競爭并且首先得到數(shù)據(jù). 因此我們必須再次獲取設(shè)備旗標(biāo)。 只有這時我們才可以測試讀緩沖(在 while 循環(huán)中)并且真正知道我們可以返回緩沖中的數(shù)據(jù)給用戶. 全部這個代碼的最終結(jié)果是, 當(dāng)我們從 while 循環(huán)中退出時, 我們知道旗標(biāo)被獲得并且緩沖中有數(shù)據(jù)我們可以用.僅僅為了完整, 我們要注意, scull_p_read 可以在另一個地方睡眠, 在我們獲得設(shè)備旗標(biāo)之后: 對 copy_to_user 的調(diào)用. 如果 scull 當(dāng)在內(nèi)核和用戶空間之間拷貝數(shù)據(jù)時睡眠, 它在持有設(shè)備旗標(biāo)中睡眠. 在這種情況下持有旗標(biāo)是合理的因為它不能死鎖系統(tǒng)(我們知道內(nèi)核將進(jìn)行拷貝到用戶空間并且在不加鎖進(jìn)程中的同一個旗標(biāo)下喚醒我們), 并且因為重要的是設(shè)備內(nèi)存數(shù)組在驅(qū)動睡眠時不改變..高級睡眠許多驅(qū)動能夠滿足它們的睡眠要求, 使用至今我們已涉及到的函數(shù). 但是, 有時需要深入理解 Linux 等待隊列機(jī)制如何工作. 復(fù)雜的加鎖或者性能需要可強制一個驅(qū)動來使用低層函數(shù)來影響一個睡眠. 在本節(jié), 我們在低層看而理解在一個進(jìn)程睡眠時發(fā)生了什么..一個進(jìn)程如何睡眠如果我們深入 linux/, 你見到在 wait_queue_head_t 類型后面的數(shù)據(jù)結(jié)構(gòu)是非常簡單的。 它包含一個自旋鎖和一個鏈表. 這個鏈表是一個等待隊列入口, 它被聲明做 wait_queue_t. 這個結(jié)構(gòu)包含關(guān)于睡眠進(jìn)程的信息和它想怎樣被喚醒.使一個進(jìn)程睡眠的第一步常常是分配和初始化一個 wait_queue_t 結(jié)構(gòu), 隨后將其添加到正確的等待隊列. 當(dāng)所有東西都就位了, 負(fù)責(zé)喚醒工作的人就可以找到正確的進(jìn)程.下一步是設(shè)置進(jìn)程的狀態(tài)來標(biāo)志它為睡眠. 在 linux/ 中定義有幾個任務(wù)狀態(tài). TASK_RUNNING 意思是進(jìn)程能夠運行, 盡管不必在任何特定的時刻在處理器上運行. 有 2 個狀態(tài)指示一個進(jìn)程是在睡眠: TASK_INTERRUPTIBLE 和 TASK_UNTINTERRUPTIBLE。 當(dāng)然, 它們對應(yīng) 2 類的睡眠. 其他的狀態(tài)正常地和驅(qū)動編寫者無關(guān).在 內(nèi)核, 對于驅(qū)動代碼通常不需要直接操作進(jìn)程狀態(tài). 但是, 如果你需要這樣做, 使用的代碼是:void set_current_state(int new_state)。 在老的代碼中, 你常常見到如此的東西:currentstate = TASK_INTERRUPTIBLE。 但是象這樣直接改變 current 是不鼓勵的。 當(dāng)數(shù)據(jù)結(jié)構(gòu)改變時這樣的代碼會輕易地失效. 但是, 上面的代碼確實展示了自己改變一個進(jìn)程的當(dāng)前狀態(tài)不能使其睡眠. 通過改變 current 狀態(tài), 你已改變了調(diào)度器對待進(jìn)程的方式, 但是你還未讓出處理器.放棄處理器是最后一步, 但是要首先做一件事: 你必須先檢查你在睡眠的條件. 做這個檢查失敗會引入一個競爭條件。 如果在你忙于上面的這個過程并且有其他的線程剛剛試圖喚醒你, 如果這個條件變?yōu)檎鏁l(fā)生什么? 你可能錯過喚醒并且睡眠超過你預(yù)想的時間. 因此, 在睡眠的代碼下面, 典型地你會見到下面的代碼:if (!condition) schedule()。通過在設(shè)置了進(jìn)程狀態(tài)后檢查我們的條件, 我們涵蓋了所有的可能的事件進(jìn)展. 如果我們在等待的條件已經(jīng)在設(shè)置進(jìn)程狀態(tài)之前到來, 我們在這個檢查中注意到并且不真正地睡眠. 如果之后發(fā)生了喚醒, 進(jìn)程被置為可運行的不管是否我們已真正進(jìn)入睡眠.調(diào)用 schedule , 當(dāng)然, 是引用調(diào)度器和讓出 CPU 的方式. 無論何時你調(diào)用這個函數(shù), 你是在告訴內(nèi)核來考慮應(yīng)當(dāng)運行哪個進(jìn)程并且轉(zhuǎn)換控制到那個進(jìn)程, 如果必要. 因此你從不知道在 schedule 返回到你的代碼會是多長時間.在 if 測試和可能的調(diào)用 schedule (并從其返回)之后, 有些清理工作要做. 因為這個代碼不再想睡眠, 它必須保證任務(wù)狀態(tài)被重置為 TASK_RUNNING. 如果代碼只是從 schedule 返回, 這一步是不必要的。 那個函數(shù)不會返回直到進(jìn)程處于可運行態(tài). 如果由于不再需要睡眠而對 schedule 的調(diào)用被跳過, 進(jìn)程狀態(tài)將不正確. 還有必要從等待隊列中去除這個進(jìn)程, 否則它可能被多次喚醒..手動睡眠在 Linux 內(nèi)核的之前的版本, 正式的睡眠要求程序員手動處理所有上面的步驟. 它是一個繁瑣的過程, 包含相當(dāng)多的易出錯的樣板式的代碼. 程序員如果愿意還是可能用那種方式手動睡眠。 linux/ 包含了所有需要的定義, 以及圍繞例子的內(nèi)核源碼. 但是, 有一個更容易的方式.第一步是創(chuàng)建和初始化一個等待隊列. 這常常由這個宏定義完成:DEFINE_WAIT(my_wait)。 其中, name 是等待隊列入口項的名子. 你可用 2 步來做:wait_queue_t my_wait。init_wait(amp。my_wait)。但是常常更容易的做法是放一個 DEFINE_WAIT 行在循環(huán)的頂部, 來實現(xiàn)你的睡眠.下一步是添加你的等待隊列入口到隊列, 并且設(shè)置進(jìn)程狀態(tài). 2 個任務(wù)都由這個函數(shù)處理:void prepare_to_wait(wait_queue_head_t *queue, wait_queue_t *wait, int state)。 這里, queue 和 wait 分別地是等待隊列頭和進(jìn)程入口. state 是進(jìn)程的新狀態(tài)。 它應(yīng)當(dāng)或者是 TASK_INTERRUPTIBLE(給可中斷的睡眠, 這常常是你所要的)或者 TASK_UNINTERRUPTIBLE(給不可中斷睡眠).在調(diào)用 prepare_to_wait 之后, 進(jìn)程可調(diào)用 schedule 在它已檢查確認(rèn)它仍然需要等待之后. 一旦 schedule 返回, 就到了清理時間. 這個任務(wù), 也, 被一個特殊的函數(shù)處理:void finish_wait(wait_queue_head_t *queue, wait_queue_t *wait)。 之后, 你的代碼可測試它的狀態(tài)并且看是否它需要再次等待.我們早該需要一個例子了. 之前我們看了 給 scullpipe 的 read 方法, 它使用 wait_event. 同一個驅(qū)動中的 write 方法使用 prepare_to_wait 和 finish_wait 來實現(xiàn)它的等待. 正常地, 你不會在一個驅(qū)動中象這樣混用各種方法, 但是我們這樣作是為了能夠展示 2 種處理睡眠的方式.為完整起見, 首先, 我們看 write 方法本身:/* How much space is free? */static int spacefree(struct scull_pipe *dev){ if (devrp == devwp) return devbuffersize 1。 return ((devrp + devbuffersize devwp) % devbuffersize) 1。}static ssize_t scull_p_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos){ struct scull_pipe *dev = filpprivate_data。 int result。 if (down_interruptible(amp。devsem)) return ERESTARTSYS。 /* Make sure there39。s space to write */ result = scull_getwritespace(dev, filp)。 if (result) return result。 /* scull_getwritespace called up(amp。devsem) */ /* ok, space is there, accept something */ count = min(count, (size_t)spacefree(dev))。 if (devwp = devrp) count = min(count, (size_t)(devend devwp))。 /* to endofbuf */ else /* the write pointer has wrapped, fill up to rp1 */ count = min(count, (size_t)(devrp devwp 1))。 PDEBUG(Going to accept %li bytes to %p from %p\n, (long)count, devwp, buf)。 if (copy_from_user(devwp, buf, count)) { up (amp。devsem)。 return EFAULT。 } devwp += count。 if (devwp == devend) devwp = devbuffer。 /* wrapped */ up(amp。devsem)。 /* finally, awake any reader */ wake_up_interruptible(amp。devinq)。 /* blocked in read() and select() */ /* and signal asynchronous readers, explained late in chapter 5 */ if (devasync_queue) kill_fasync(amp。devasync_queue, SIGIO, POLL_IN)。 PDEBUG(\%s\ did write %li bytes\n,currentm, (long)count)。 return count。}這個代碼看來和 read 方法類似, 除了我們已經(jīng)將睡眠代碼放到了一個單獨的函數(shù), 稱為 scull_getwritespace. 它的工作是確保在緩沖中有空間給新的數(shù)據(jù), 睡眠直到有空間可用. 一旦空間在, scull_p_write 可簡單地拷貝用戶的數(shù)據(jù)到那里, 調(diào)整指針, 并且喚醒可能已經(jīng)在等待讀取數(shù)據(jù)的進(jìn)程.處理實際的睡眠的代碼是:/* Wait for space for writing。 caller must hold device semaphore. On * error the semaphore will be released before returning. */static int scull_getwritespace(struct scull_pipe *dev, struct file *filp){ while (spacefree(dev) == 0) { /* full */ DEFINE_WAIT(wait)。 up(amp。devsem)。 if (filpf_flags amp。 O_NONBLOCK) return EAGAIN。 PDEBUG(\%s\ writing: going to sleep\n,currentm)。 prepare_to_wait(amp。devoutq, amp。wait, TASK_INTERRUPTIBLE)。 if (spacefree(dev) == 0) schedule()。 finish_wait(amp。devoutq, amp。wait)。 if (signal_pending(current)) return ERESTARTSYS。 /* signal: tell the fs layer to handle it */ if (down_interruptible(amp。devsem)) return ERESTARTSYS。 } return 0。}再次注意 while 循環(huán). 如果有空間可用而不必睡眠, 這個函數(shù)簡單地返回. 否則, 它必須丟掉設(shè)備旗標(biāo)并且等待. 這個代碼使用 DE
點擊復(fù)制文檔內(nèi)容
公司管理相關(guān)推薦
文庫吧 www.dybbs8.com
備案圖鄂ICP備17016276號-1