linux下的關(guān)機(jī)和重啟流程對于一般的桌面應(yīng)用和網(wǎng)絡(luò)服務(wù)器來說并不重要,但是在用戶自己定義的嵌入式系統(tǒng)內(nèi)核中就有一定的研究意義,通過了解Linux 關(guān)機(jī)重啟的流程,我們對它可以修改和自定義,甚至以此為基礎(chǔ)開發(fā)出全新的功能來 。
1.概述
在linux下的關(guān)機(jī)和重啟可能由兩種行為引發(fā),一是通過用戶編程,一是系統(tǒng)自己產(chǎn)生的消息 。用戶和系統(tǒng)進(jìn)行交互的方式也有兩個(gè),一個(gè)是系統(tǒng)調(diào)用:sys_reboot,另一個(gè)就是apm或則acpi的設(shè)備文件,通過對其操作也可以使系統(tǒng)關(guān)機(jī)或者重啟 。
2.通過系統(tǒng)調(diào)用sys_reboot的重啟
這個(gè)系統(tǒng)調(diào)用定義了一系列的MAGIC_NUMBER,在調(diào)用的開始部分首先檢查MAGIC_NUMBER是否正確,只有正確才繼續(xù)向下運(yùn)行 。在重啟的時(shí)候轉(zhuǎn)向分支
case LINUX_REBOOT_CMD_RESTART:
首先使用notifier_call_chain向其它部分發(fā)出重啟的消息,然后調(diào)用machine_restart函數(shù)完成重啟 。
machine_restart函數(shù)的開始部分有一段SMP相關(guān)的代碼,主要完成多CPU時(shí)由一個(gè)CPU完成重啟操作,其它CPU處于等待狀態(tài) 。之后系統(tǒng)根據(jù)一個(gè)變量reboot_thru_bios的內(nèi)容判斷重啟方式,通過閱讀reboot_setup我們可以得知,這個(gè)參數(shù)的內(nèi)容是在系統(tǒng)啟動時(shí)指定的,決定了是否利用bios,事實(shí)上是系統(tǒng)復(fù)位后的入口(FFFF:0000)地址的程序進(jìn)行重啟 。在不通過bios進(jìn)行重啟的情況下,系統(tǒng)首先設(shè)定了重啟標(biāo)志,然后向端口0xfe寫入數(shù)字0x64,這種重啟的具體原理我還不大清楚,似乎是模擬了一次reset鍵的按下,希望大家和我討論 。在通過bios重啟的情況下,系統(tǒng)同樣先設(shè)定了重啟模式,然后切換到了實(shí)模式,通過一條ljmp $0xffff,$0x0完成了重啟 。
3.通過系統(tǒng)調(diào)用sys_reboot進(jìn)行關(guān)機(jī)
在系統(tǒng)調(diào)用的處理分支上,我們可以看到,首先同樣是檢查MAGIC_NUMBER,然后在
case LINUX_REBOOT_CMD_POWER_OFF:
的執(zhí)行流程里面,又是使用notifier_call_chain發(fā)出了關(guān)閉計(jì)算機(jī)電源的消息,緊接著執(zhí)行了machine_power_off函數(shù) 。我們在machine_power_off函數(shù)中可以看到,如果pm_power_off這個(gè)函數(shù)指針不為空,那么系統(tǒng)就會通過調(diào)用這個(gè)函數(shù)進(jìn)行關(guān)機(jī) 。在apm已經(jīng)加載的情況下(SMP除外),實(shí)際上pm_power_off函數(shù)實(shí)際上指向了apm.c中的apm_power_off,在這個(gè)函數(shù)里系統(tǒng)通過apm_info結(jié)構(gòu)里的值,使用切換到實(shí)模式關(guān)機(jī),或者使用apm_bios_call_simple函數(shù)調(diào)用保護(hù)模式下的apm接口關(guān)機(jī)兩種方法 。
4.apm驅(qū)動本身的關(guān)機(jī)過程
apm使用其注冊的設(shè)備的ioctl接口完成apm的操作,在apm.c的do_ioctl函數(shù)中可以看見處理的分支 。這里只有suspend和standby的代碼,所以我們不能通過ioctl這種方法使用apm關(guān)機(jī) 。
當(dāng)用戶按下POWER開關(guān)的時(shí)候,如果有apm模塊,那么關(guān)機(jī)流程是由apm來處理的 。apm驅(qū)動在初始化的時(shí)候啟動了一個(gè)apm內(nèi)核線程:apm_mainloop,系統(tǒng)會在這里檢測到POWEROFF按鍵消息并且將其命名為APM_SYS_SUSPEND,以區(qū)別apm -s設(shè)置的APM_USER_SUSPEND模式 。緊接著進(jìn)入了apm_event_handler函數(shù),又從apm_event_handler函數(shù)進(jìn)入了check_events函數(shù),處理函數(shù)對應(yīng)的case分支上 。系統(tǒng)同樣使用了suspend函數(shù)進(jìn)行關(guān)機(jī),不過由于其它參數(shù)的原因,suspend最后調(diào)用的是關(guān)機(jī)的流程 。
5.解決問題實(shí)例
1)按POWER鍵時(shí)某些主板死機(jī)
經(jīng)查只有某些特定的驅(qū)動裝載之后才會出現(xiàn)這樣的情況,并且當(dāng)使用關(guān)機(jī)系統(tǒng)調(diào)用sys_reboot的時(shí)候沒有這樣的問題 。分析apm的處理流程,懷疑是在關(guān)機(jī)前驅(qū)動程序沒有正確處理apm發(fā)出的詢問消息造成的 。由于部分驅(qū)動程序沒有源代碼,決定hack掉apm.c的關(guān)機(jī)部分,讓兩種方式的關(guān)機(jī)走同樣的流程 。于是把a(bǔ)pm.c的check_events函數(shù)中對APM_SYS_SUSPEND部分改寫為如下代碼:
推薦閱讀
- 在Linux下成功運(yùn)行最新的QQ和MSN
- 如何給linux添加新硬盤
- Linux操作系統(tǒng)下機(jī)器溫度監(jiān)控與調(diào)整方法
- 實(shí)用技巧:UNIX和Linux實(shí)現(xiàn)NFS共享連接
- 八 讀核日記 --linux的內(nèi)存管理機(jī)制(2)
- 七 讀核日記 --linux的內(nèi)存管理機(jī)制(1)
- 三 讀核日記
- 如何同時(shí)啟動6個(gè)X控制臺
- 蘋果xs屏幕失靈怎么強(qiáng)制關(guān)機(jī)
- Linux與分區(qū)
