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 */一句話,如果你不想支援電源管理,那麼你編譯核心時把config_pm給關了。不過,有乙個問題,usb裝置實際上是有節電這個特性的,也就是說usb的各種規範中就有乙個suspend和乙個resume,也就是掛起和恢復,換而言之,硬體本身有這樣的特性,要是軟體不支援的話寫出來的**你敢給客戶用嗎?不過乙個利好訊息是,除了這裡這個try_to_freeze()比較難一點外,剩下的在usb中出現的電源管理的**實際上相對來說不是很難理解,畢竟那些東西和硬體規範是對應的,都有章可循,硬體怎麼規定就怎麼做,所以,不用太擔心。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 */
擺平了外面的這行**,於是現在我們安心來看hub_events()了。hub_events()還是來自drivers/usb/core/hub.c,我們一段一段地來看。
2595 static void hub_events(void)2615行,乙個while(1)迴圈;2619行,判斷hub_event_list是否為空,是不是覺得很有趣?第一次呼叫這個函式時,hub_event_list就是初值,我們說過初值為空,所以這裡就是空,即list_empty()返回1,然後break語句跳出while迴圈。你知道while迴圈的結尾在**嗎?就是這個hub_events()函式的結尾,也就是說在這裡幾百行的**就結束了,我們直接退出這個函式,返回到hub_thread()中,呼叫wait_event_interruptible()進入睡眠,然後等待有事件發生。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);
對於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標記,用線段樹區間維護,然...