Linux 内核完成接口
生活随笔
收集整理的這篇文章主要介紹了
Linux 内核完成接口
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
Linux 內(nèi)核里面有一個函數(shù)wait_for_completion,這是一個內(nèi)核同步機制的函數(shù),同步機制如果是早期的讀者應(yīng)該看過我發(fā)的文章,如果沒有看過的可以看看Linux 專輯文章里面找找。
既然是同步機制,主要的工作就是調(diào)用了這個函數(shù),程序就會等另外的事件完成之后再繼續(xù)下面的工作。
wait_for_completion 結(jié)構(gòu)體
/**?struct?completion?-?structure?used?to?maintain?state?for?a?"completion"**?This?is?the?opaque?structure?used?to?maintain?the?state?for?a?"completion".*?Completions?currently?use?a?FIFO?to?queue?threads?that?have?to?wait?for*?the?"completion"?event.**?See?also:??complete(),?wait_for_completion()?(and?friends?_timeout,*?_interruptible,?_interruptible_timeout,?and?_killable),?init_completion(),*?reinit_completion(),?and?macros?DECLARE_COMPLETION(),*?DECLARE_COMPLETION_ONSTACK().*/ struct?completion?{unsigned?int?done;wait_queue_head_t?wait; };結(jié)構(gòu)體里面就兩個東西,一個是 done,一個是隊列wait。
還有他相關(guān)的函數(shù)
complete() wait_for_completion()? init_completion() reinit_completion() DECLARE_COMPLETION() DECLARE_COMPLETION_ONSTACK().如何使用?
先聲明
struct?completion?bl_ready; init_completion(&ts->bl_ready);需要等待退出的線程
static?irqreturn_t?cyttsp_irq(int?irq,?void?*handle) {struct?cyttsp?*ts?=?handle;int?error;/*退出的時候會設(shè)置為CY_BL_STATE*//*在這里做判斷*/if?(unlikely(ts->state?==?CY_BL_STATE))?{complete(&ts->bl_ready);goto?out;} }退出時候調(diào)用
static?int?cyttsp_soft_reset(struct?cyttsp?*ts) {unsigned?long?timeout;int?retval;/*?wait?for?interrupt?to?set?ready?completion?*/reinit_completion(&ts->bl_ready);/*退出的時候會設(shè)置為?CY_BL_STATE*/ts->state?=?CY_BL_STATE;enable_irq(ts->irq);retval?=?ttsp_send_command(ts,?CY_SOFT_RESET_MODE);if?(retval)goto?out;timeout?=?wait_for_completion_timeout(&ts->bl_ready,msecs_to_jiffies(CY_DELAY_DFLT?*?CY_DELAY_MAX));retval?=?timeout???0?:?-EIO;out:ts->state?=?CY_IDLE_STATE;disable_irq(ts->irq);return?retval; }里面的實現(xiàn)細(xì)節(jié)
三個函數(shù)的流程
init_completion 初始化
我們看init 初始化的代碼
static?inline?void?init_completion(struct?completion?*x) {x->done?=?0;init_waitqueue_head(&x->wait); }static?inline?void?reinit_completion(struct?completion?*x) {x->done?=?0; }初始化的時候,把done這個變量設(shè)置為 0 。
wait_for_completion_timeout 的調(diào)用流程
static?inline?long?__sched do_wait_for_common(struct?completion?*x,long?(*action)(long),?long?timeout,?int?state) {/*如果done是0就跑到if里面去,也就說明我們等的事件還沒完成*/if?(!x->done)?{DECLARE_WAITQUEUE(wait,?current);__add_wait_queue_tail_exclusive(&x->wait,?&wait);do?{if?(signal_pending_state(state,?current))?{timeout?=?-ERESTARTSYS;break;}__set_current_state(state);spin_unlock_irq(&x->wait.lock);timeout?=?action(timeout);/*休眠timeout時間等待*/spin_lock_irq(&x->wait.lock);}?while?(!x->done?&&?timeout);/*如果事件完成了就提出*/__remove_wait_queue(&x->wait,?&wait);if?(!x->done)return?timeout;}x->done--;return?timeout??:?1; }內(nèi)核里面有非常多這樣的小代碼,我覺得看這樣的代碼非常有意思,你需要不斷的去揣摩它,品味它。
這段代碼的主要工作就是在超時時間內(nèi)判斷done的值已經(jīng)大于0,然后退出,退出的時候把done 減去1。
總結(jié)
文章里面的實例是從一個touch驅(qū)動里面提取出來的,它的目的是為了reset觸摸屏的時候,確保中斷線程已經(jīng)完全退出了,在中斷線程里面有操作touch I2C的操作,如果reset的時候,線程還沒有跑完,驅(qū)動就會可能收到I2C報錯的異常。
?error?=?request_threaded_irq(ts->irq,?NULL,?cyttsp_irq,IRQF_TRIGGER_FALLING?|?IRQF_ONESHOT,pdata->name,?ts);內(nèi)核完成補丁
這份補丁是用來修復(fù)do_wait_for_common?這個函數(shù)的,看注釋的作用就是用一行代碼代替了幾行代碼。內(nèi)核專家做了修正,貼出來方便大家加深理解。
Change?do_wait_for_common()?to?use?signal_pending_state()?instead?of open?coding.Signed-off-by:?Oleg?Nesterov?<oleg@xxxxxxxxxx>---?26-rc2/kernel/sched.c~1_SPS_WAIT_FOR?2008-07-22?18:36:58.000000000?+0400 +++?26-rc2/kernel/sched.c?2008-07-24?19:54:12.000000000?+0400 @@?-4735,10?+4735,7?@@?do_wait_for_common(struct?completion?*x, wait.flags?|=?WQ_FLAG_EXCLUSIVE; __add_wait_queue_tail(&x->wait,?&wait); do?{ -?if?((state?==?TASK_INTERRUPTIBLE?&& -?signal_pending(current))?|| -?(state?==?TASK_KILLABLE?&& -?fatal_signal_pending(current)))?{ +?if?(signal_pending_state(state,?current))?{ timeout?=?-ERESTARTSYS; break; }-- To?unsubscribe?from?this?list:?send?the?line?"unsubscribe?linux-kernel"?in the?body?of?a?message?to?majordomo@xxxxxxxxxxxxxxx More?majordomo?info?at?http://vger.kernel.org/majordomo-info.html Please?read?the?FAQ?at?http://www.tux.org/lkml/推薦閱讀:
專輯|Linux文章匯總
專輯|程序人生
嵌入式Linux
微信掃描二維碼,關(guān)注我的公眾號
總結(jié)
以上是生活随笔為你收集整理的Linux 内核完成接口的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 钢琴专业打谱软件 Overture 4.
- 下一篇: WebStorm快捷键