6 等待,只因曾經承諾

2021-06-18 09:28:36 字數 4366 閱讀 1970

6.等待,只因曾經承諾

hub_thread()中還有乙個函式沒有講,它就是try_to_freeze(),這是與電源管理相關的函式。對大多數人來說,關於這個函式,了解就可以了。

隨著linux開始支援suspended之後,有人提倡,每乙個核心程序都應該在適當的時候,呼叫try_to_freeze()。什麼意思呢?有這樣乙個flag,pf_nofreeze,如果你這個程序或者核心執行緒不想進入suspended狀態,那麼你就可以設定這個flag,正如我們在usb-storage中usb_stor_control_thread()中做的那樣。而對於大多數核心執行緒來說,目前主流的看法是希望你能在某個地方呼叫try_to_freeze(),這個函式的作用是檢測乙個flag有沒有設定,哪個flag呢,tif_freeze,每個體系結構定義了自己與這有關的flags,比如i386的,include/asm- i386/thread_info.h中:

126 #define tif_syscall_trace       0       /* syscall trace active */  

127 #define tif_notify_resume     1  /* resumption notification requested */  

128 #define tif_sigpending          2       /* signal pending */  

129 #define tif_need_resched        3       /* rescheduling necessary */  

130 #define tif_singlestep  4 /* restore singlestep on return to user mode*/  

131 #define tif_iret                5       /* return with iret */  

132 #define tif_syscall_emu         6       /* syscall emulation active */  

133 #define tif_syscall_audit       7       /* syscall auditing active */  

134 #define tif_seccomp             8       /* secure computing */  

135 #define tif_restore_sigmask   9 /* restore signal mask in do_signal() */  

136 #define tif_memdie              16  

137 #define tif_debug               17      /* uses debug registers */  

138 #define tif_io_bitmap           18      /* uses i/o bitmap */  

139 #define tif_freeze              19      /* is freezing for suspend */  

一句話,如果你不想支援電源管理,那麼你編譯核心時把config_pm給關了。不過,有乙個問題,usb裝置實際上是有節電這個特性的,也就是說usb的各種規範中就有乙個suspend和乙個resume,也就是掛起和恢復,換而言之,硬體本身有這樣的特性,要是軟體不支援的話寫出來的**你敢給客戶用嗎?不過乙個利好訊息是,除了這裡這個try_to_freeze()比較難一點外,剩下的在usb中出現的電源管理的**實際上相對來說不是很難理解,畢竟那些東西和硬體規範是對應的,都有章可循,硬體怎麼規定就怎麼做,所以,不用太擔心。

擺平了外面的這行**,於是現在我們安心來看hub_events()了。hub_events()還是來自drivers/usb/core/hub.c,我們一段一段地來看。

2595 static void hub_events(void)  

2596   

2623  

2624        

tmp= 

hub_event_list

.next;  

2625        list_del_init(tmp);  

2626  

2627        

hub= 

list_entry

(tmp, struct usb_hub, event_list);  

2628        

hdev

= hub

->

hdev;  

2629        

intf

= to_usb_inte***ce

(hub-

>

intfdev);  

2630        

hub_dev

= &intf-

>

dev;  

2631  

2632        dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n",  

2633                                 hdev-

>

state, hub-

>

descriptor  

2634                                         ? hub-

>

descriptor-

>

bnbrports  

2635                                         : 0,  

2636                            /* note: expects max 15 ports... */  

2637                                 (u16) hub-

>

change_bits[0],  

2638                                 (u16) hub-

>

event_bits[0]);  

2639  

2640            usb_get_intf(intf);  

2641        spin_unlock_irq(&hub_event_lock);  

2615行,乙個while(1)迴圈;2619行,判斷hub_event_list是否為空,是不是覺得很有趣?第一次呼叫這個函式時,hub_event_list就是初值,我們說過初值為空,所以這裡就是空,即list_empty()返回1,然後break語句跳出while迴圈。你知道while迴圈的結尾在**嗎?就是這個hub_events()函式的結尾,也就是說在這裡幾百行的**就結束了,我們直接退出這個函式,返回到hub_thread()中,呼叫wait_event_interruptible()進入睡眠,然後等待有事件發生。

對於hub來說,當你插入乙個裝置到hub口裡,就會觸發一件事件。而第一件事件的發生其實是hub驅動程式本身的初始化,即我們說過,由於root hub的存在,所以hub_probe必然會被呼叫,確切地說,就是在主機控制器的驅動程式中,一定會呼叫hub_probe的。如果你問我到底什麼時候會呼叫,那麼我無可奉告,因為這是在主機控制器的驅動程式中,不管你的主機控制器是屬於ohci的、uhci的,還是ehci的,最終在它們的初始化**中都會呼叫乙個叫做hcd_register_root()的函式,進而轉到usb_register_root_hub(),幾經周轉,最終hub_probe就會被呼叫。所以你根本不用擔心這個函式什麼時刻會被呼叫,反正總會有這個時刻。

所以,我們就轉到hub_probe吧,這裡hub_events()只是虛晃一槍,不過你別忘了,等到hub_event_list裡面有東西了之後,我們還會回來的。要知道hub_events()這個函式才是真正的hub驅動的核心函式,所有的故事都是在這裡發生的。所以,就像你給了某人乙個承諾,承諾你還會回來。有了承諾,等待也被賦予了意義。

最後需要記住的是wait_event_interruptible()的第乙個引數是&khubd_wait,關於這個函式我們在usb-storage裡面已經看過多次了,其中khubd_wait定義於drivers/usb/core/hub.c:

85 /* wakes up khubd */  

86 static declare_wait_queue_head(khubd_wait); 

這無非就是乙個等待佇列頭,所以我們很清楚,將來要喚醒這個睡眠程序的一定是類似這樣的一行**:wake_up(&khubd_wait)。沒錯,整個核心**中只有乙個地方會呼叫這個**,那就是kick_khubd(),不過呼叫kick_khubd()的地方可不少。

Selenium筆記(6)等待

1.簡介 在selenium操作瀏覽器的過程中,每一次請求url,selenium都會等待頁面載入完畢以後,才會將操作許可權再次交給我們的程式。但是,由於ajax和各種js 的非同步載入問題,所以我們在使用selenium的時候常常會遇到操作的元素還沒有載入出來,就會引發報錯。為了解決這個問題,se...

3 1等待 通知機制(wait notify)

要點 wait 執行前在呼叫wait 之前,必須先要獲得物件鎖,即只有在同步方法或者同步 塊中呼叫wait 方法。執行作用 wait 使程序進入等待 阻塞狀態 在收到通知或者被中斷之前都會進入預執行佇列。執行之後1 執行wait 之後,當前執行緒釋放改物件鎖,在通知前與其他執行緒重新競爭資源 執行之...

XDOJ1156 等待佇列

題意 大概就是有三種操作吧,第一種在佇列後面加入新人,引入乙個不耐煩程度,第二種第乙個人出隊 直接讓頭結點的序號 1即可 第三種統計在隊伍裡面不耐煩程度最高的數 ps 隨著操作的進行佇列中每乙個人的不耐煩程度 1 剛開始我是將每個節點加入線段樹中,對於每個操作,打上lazy標記,用線段樹區間維護,然...