Printk實現流程

一、初步結論
1.如何把字符串放到緩存,如何從緩存寫到串口。
首先是在關中斷,關調度,保持logbuf_lock自旋鎖的情況下,將數據格式化後,放到printk_buf緩衝區,其大小爲1K,也就是說,每次printk只能打印1K的內容。格式化完畢後,將數據再複製到log_buf緩衝區。由於在向串口輸出的過程中,會暫時打開自旋鎖,所以在SMP下,其他CPU可能繼續向log_buf中存放數據,並由驅動輸出。簡單的說:調用一次printk,需要打印的並不僅僅是本次printk需要輸出的內容,還可能有其他CPU上輸出的內容。
從緩存中輸出到真實的設備是由註冊的控制檯個數決定的。註冊多少個設備,就向多少個設備輸出。也就是說,如果註冊了兩個串口控制檯,那麼關中斷的時間就會增加一倍。
2.採用中斷還是輪詢。
採用的是輪詢方式。

二、代碼流程詳細分析
Printk的主要流程由vprintk輔助函數實現。
Vprintk的流程如下:

1.關搶佔。這是因爲需要調用smp_processor_id,如果不關調度,並且是在異常或者內核線程中調用printk的話,可能會導致任務飄移到其他CPU,從而導致後續邏輯判斷錯誤。
2.如果當前上下文是在異常中,那麼異常可能是printk引起的,由於後續會使用logbuf_lock自旋鎖,爲了防止自旋鎖嵌套,導致系統死鎖,調用zap_locks,復位自旋鎖。
3.關中斷,並獲得logbuf_lock自旋鎖,以保護printk_buf緩衝區,這樣即使是在SMP上,printk打印出來的內容都不會交錯輸出。
4.將格式化的信息輸出到printk_buf緩衝區,並複製到log_buf。
5.使用down_trylock非阻塞的申請console_sem信號量。視情況進入以下處理流程:
A:如果申請成功,則將log_buf中的內容輸出到物理設備上。
B:如果申請失敗,則開中斷並釋放自旋鎖,並退出。本次輸出到printk_buf緩衝區的內容,由其他printk執行路徑輸出到物理設備上。所以,某次printk輸出到物理設備上的內容,並不一定僅僅是本次傳遞給printk的內容,還有可能是其他CPU上的printk輸出到緩衝區中的內容。

當printk向緩衝區輸出申請console_sem信號量成功後,printk會向物理設備輸出,在這個過程中,會臨時釋放自旋鎖,以允許其他CPU向緩衝區中輸出內容。具體流程如下:
1.暫時釋放logbuf_lock自旋鎖,這樣,其他CPU可以向log_buf緩衝區中輸出數據。
2.調用release_console_sem向物理設備輸出內容。
3.release_console_sem首先在循環執行如下流程:
A:得到當前log_buf緩衝區的起始地址和物理地址。如果沒有新的數據,則退出。新的數據可能是其他cpu調用printk輸出到緩衝區中的。
B:打開自旋鎖,允許其他CPU向緩衝區中輸出數據。
C:調用call_console_drivers將當前緩衝區中的內容輸出到物理設備。本次輸出的內容,不包含釋放自旋鎖後,其他CPU向緩衝區中輸出的內容。
4. 循環結束後,release_console_sem判斷本次printk是否確實輸出了數據(當printk參數爲空串時,可能沒有數據),如果有數據輸出,就喚醒klogd進程。

call_console_drivers函數首先將輸出內容按行分拆,並將每行數據傳遞給當前註冊的所有控制檯設備,調用控制檯驅動將數據打印出來。由於整個過程都處於關中斷狀態,所以,只要某個註冊的控制檯驅動是慢速設備,都會影響到關中斷的時間。更爲嚴重的是:如果某個CPU在調用printk輸出期間,其他CPU也準備向控制檯輸出,那麼其他CPU也會因爲申請不到logbuf_lock自旋鎖而處於忙等狀態。

串口驅動函數:
耗時的過程是向串口等慢速設備輸出數據的過程。由於printk可以在中斷中使用,所以也決定了驅動不能採用中斷方式,而必須是輪詢串口的方式。

8250串口驅動回調函數serial8250_console_write實現了控制檯write回調。這個函數的流程如下:
1.首先調用一下NMI軟件狗回調函數。看來串口驅動已經意識到慢速設備對系統的影響了。但是這個回調沒有辦法解決硬件狗的問題。
2.關中斷。
3.對需要輸出的每個字符,回調serial8250_console_putchar函數。
4.最費時的地方就在serial8250_console_putchar中。它調用wait_for_xmitr(up, UART_LSR_THRE);一句,輪詢串口狀態。直到串口可寫,才向串口輸出一個字符。
5.恢復中斷狀態。實際上,在printk上下文中,中斷此時仍然是關閉的,直到log_buf緩衝區中的所有數據都輸出到串口。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章