資料介紹
Linux 下的關機和重啟流程對于一般的桌面應用和網絡服務器來說并不重要,但是在用戶自己定義的嵌入式系統內核中就有一定的研究意義,通過了解 Linux 關機重啟的流程,我們對它可以修改和自定義,甚至以此為基礎開發出全新的功能來。
1. 概述
在 Linux 下的關機和重啟可能由兩種行為引發,一是通過用戶編程,一是系統自己產生的消息。用戶和系統進行交互的方式也有兩個,一個是系統調用:sys_reboot,另一個就是 apm 或則 acpi 的設備文件,通過對其操作也可以使系統關機或者重啟。
2. 通過系統調用 sys_reboot 的重啟
這個系統調用定義了一系列的 MAGIC_NUMBER,在調用的開始部分首先檢查 MAGIC_NUMBER 是否正確,只有正確才繼續向下運行。在重啟的時候轉向分支
case Linux _REBOOT_CMD_RESTART:
首先使用 notifier_call_chain 向其它部分發出重啟的消息,然后調用 machine_restart 函數完成重啟。
machine_restart 函數的開始部分有一段SMP相關的代碼,主要完成多 CPU 時由一個 CPU 完成重啟操作,其它 CPU 處于等待狀態。之后系統根據一個變量 reboot_thru_bios 的內容判斷重啟方式,通過閱讀 reboot_setup 我們可以得知,這個參數的內容是在系統啟動時指定的,決定了是否利用 bios,事實上是系統復位后的入口 (FFFF:0000) 地址的程序進行重啟。在不通過 bios 進行重啟的情況下,系統首先設定了重啟標志,然后向端口 0xfe 寫入數字 0x64,這種重啟的具體原理我還不大清楚,似乎是模擬了一次 reset 鍵的按下,希望大家和我討論。在通過 bios 重啟的情況下,系統同樣先設定了重啟模式,然后切換到了實模式,通過一條 ljmp $0xffff,$0x0 完成了重啟。
3. 通過系統調用 sys_reboot 進行關機
在系統調用的處理分支上,我們可以看到,首先同樣是檢查 MAGIC_NUMBER,然后在
case Linux _REBOOT_CMD_POWER_OFF:
的執行流程里面,又是使用 notifier_call_chain 發出了關閉計算機電源的消息,緊接著執行了 machine_power_off 函數。我們在 machine_power_off 函數中可以看到,如果 pm_power_off 這個函數指針不為空,那么系統就會通過調用這個函數進行關機。在 apm 已經加載的情況下 (SMP 除外),實際上 pm_power_off 函數實際上指向了 apm.c 中的 apm_power_off,在這個函數里系統通過 apm_info 結構里的值,使用切換到實模式關機,或者使用 apm_bios_call_simple 函數調用保護模式下的 apm 接口關機兩種方法。
4. apm 驅動本身的關機過程
apm 使用其注冊的設備的 ioctl 接口完成 apm 的操作,在 apm.c的do_ioctl 函數中可以看見處理的分支。這里只有 suspend 和 standby 的代碼,所以我們不能通過 ioctl 這種方法使用 apm 關機。
當用戶按下 POWER 開關的時候,如果有 apm 模塊,那么關機流程是由 apm 來處理的。apm 驅動在初始化的時候啟動了一個 apm 內核線程:apm_mainloop,系統會在這里檢測到 POWEROFF 按鍵消息并且將其命名為 APM_SYS_SUSPEND,以區別 apm -s 設置的 APM_USER_SUSPEND 模式。緊接著進入了 apm_event_handler 函數,又從 apm_event_handler 函數進入了 check_events 函數,處理函數對應的 case 分支上。系統同樣使用了 suspend 函數進行關機,不過由于其它參數的原因,suspend 最后調用的是關機的流程。
5. 解決問題實例
1) 按 POWER 鍵時某些主板死機
經查只有某些特定的驅動裝載之后才會出現這樣的情況,并且當使用關機系統調用 sys_reboot 的時候沒有這樣的問題。分析 apm 的處理流程,懷疑是在關機前驅動程序沒有正確處理 apm 發出的詢問消息造成的。由于部分驅動程序沒有源代碼,決定 hack 掉 apm.c 的關機部分,讓兩種方式的關機走同樣的流程。于是把 apm.c 的 check_events 函數中對 APM_SYS_SUSPEND 部分改寫為如下代碼:
ret = exec_usermodehelper(poweroff_helper_path, argv, envp); if (ret) { printk(KERN_ERR “apm.c: failed to exec %s , errno = %dn”, poweroff_helper_path, errno); } break;
定義了一個用戶態應用程序 poweroff_helper_path,當 POWEROFF 鍵按下的時候系統運行這個 kernel_helper 程序。我們再寫一個通過 sys_reboot 系統調用關機的程序,放在指定的位置下。死機的問題就解決了。
2) 快速返回實模式重啟
主要可以參考了 process.c 中的返回實模式的代碼,比如我把 real_mode_switch 換成如下代碼:
// For fast reboot support static unsigned char fast_reboot_switch [] = { 0x66, 0x0f, 0x20, 0xc0, /* movl %cr0,%eax */ 0x66, 0x25, 0x10, 0x11, 0x11, 0x11, /* andl $0x11111110,%eax */ 0x66, 0x0f, 0x22, 0xc0, /* movl %eax,%cr0 */ 0xea, 0x00, 0x00, 0x00, 0x70 /* ljmp $0x7000,$0x0000 */ };
系統就可以切換到實模式中,然后跳轉到 7000H:0 位置開始執行。
6. ACPI 概述
在 2.4.20 內核中 ACPI 模塊被注明為試驗和未完成,里面有一部分功能也許沒有實現。如果 APM 和 APCI 兩個模塊同時編譯進內核,APM 在 ACPI 前被加載,APM 起作用使 ACPI 退出。對于系統電量、電源實踐一類的支持(主要是在筆記本上有用),靠的是 acpid 這個 daemon 程序。
沒有一個功能類似 apm 的應用程序切換狀態,acpi 的程序僅僅完成了對 acpi 狀態的查詢。用戶實現 S0-S4 的功能可以直接向 /proc/acpi/sleep 文件中寫入數字來實現。通過讀出 (cat) 其中的內容可以知道系統到底支持那些模式。
acpi 模塊的源代碼主程序在 linux/drivers/acpi/driver.c 中,如果向 sleep 文件寫東西,就轉到了 linux/drivers/acpi/ospm/system/sm_osl.c 文件的 sm_osl_proc_write_sleep 函數中,這個函數后來調用了 sm_osl_suspend 函數。在這個函數里完成了各種功能,包括保護各種狀態。最后真正的 sleep 是通過對 acpi_enter_sleep_state 的調用完成的,這個函數在 Linux /drivers/acpi/hardware/hwsleep.c 文件中,這里寫了 acpi 的寄存器使系統進入 sleep 狀態。寫寄存器的指令在這個目錄下面的 hwregs.c 中。
7. 總結
本文對 acpi 的介紹非常簡略,實際上 ACPI 必定會成為將來 Linux 內核中首選的電源管理方式。由于目前官方代碼中 ACPI 版本較低,所以沒有太詳細的論述,希望將來的內核能有所改進。
?
1. 概述
在 Linux 下的關機和重啟可能由兩種行為引發,一是通過用戶編程,一是系統自己產生的消息。用戶和系統進行交互的方式也有兩個,一個是系統調用:sys_reboot,另一個就是 apm 或則 acpi 的設備文件,通過對其操作也可以使系統關機或者重啟。
2. 通過系統調用 sys_reboot 的重啟
這個系統調用定義了一系列的 MAGIC_NUMBER,在調用的開始部分首先檢查 MAGIC_NUMBER 是否正確,只有正確才繼續向下運行。在重啟的時候轉向分支
case Linux _REBOOT_CMD_RESTART:
首先使用 notifier_call_chain 向其它部分發出重啟的消息,然后調用 machine_restart 函數完成重啟。
machine_restart 函數的開始部分有一段SMP相關的代碼,主要完成多 CPU 時由一個 CPU 完成重啟操作,其它 CPU 處于等待狀態。之后系統根據一個變量 reboot_thru_bios 的內容判斷重啟方式,通過閱讀 reboot_setup 我們可以得知,這個參數的內容是在系統啟動時指定的,決定了是否利用 bios,事實上是系統復位后的入口 (FFFF:0000) 地址的程序進行重啟。在不通過 bios 進行重啟的情況下,系統首先設定了重啟標志,然后向端口 0xfe 寫入數字 0x64,這種重啟的具體原理我還不大清楚,似乎是模擬了一次 reset 鍵的按下,希望大家和我討論。在通過 bios 重啟的情況下,系統同樣先設定了重啟模式,然后切換到了實模式,通過一條 ljmp $0xffff,$0x0 完成了重啟。
3. 通過系統調用 sys_reboot 進行關機
在系統調用的處理分支上,我們可以看到,首先同樣是檢查 MAGIC_NUMBER,然后在
case Linux _REBOOT_CMD_POWER_OFF:
的執行流程里面,又是使用 notifier_call_chain 發出了關閉計算機電源的消息,緊接著執行了 machine_power_off 函數。我們在 machine_power_off 函數中可以看到,如果 pm_power_off 這個函數指針不為空,那么系統就會通過調用這個函數進行關機。在 apm 已經加載的情況下 (SMP 除外),實際上 pm_power_off 函數實際上指向了 apm.c 中的 apm_power_off,在這個函數里系統通過 apm_info 結構里的值,使用切換到實模式關機,或者使用 apm_bios_call_simple 函數調用保護模式下的 apm 接口關機兩種方法。
4. apm 驅動本身的關機過程
apm 使用其注冊的設備的 ioctl 接口完成 apm 的操作,在 apm.c的do_ioctl 函數中可以看見處理的分支。這里只有 suspend 和 standby 的代碼,所以我們不能通過 ioctl 這種方法使用 apm 關機。
當用戶按下 POWER 開關的時候,如果有 apm 模塊,那么關機流程是由 apm 來處理的。apm 驅動在初始化的時候啟動了一個 apm 內核線程:apm_mainloop,系統會在這里檢測到 POWEROFF 按鍵消息并且將其命名為 APM_SYS_SUSPEND,以區別 apm -s 設置的 APM_USER_SUSPEND 模式。緊接著進入了 apm_event_handler 函數,又從 apm_event_handler 函數進入了 check_events 函數,處理函數對應的 case 分支上。系統同樣使用了 suspend 函數進行關機,不過由于其它參數的原因,suspend 最后調用的是關機的流程。
5. 解決問題實例
1) 按 POWER 鍵時某些主板死機
經查只有某些特定的驅動裝載之后才會出現這樣的情況,并且當使用關機系統調用 sys_reboot 的時候沒有這樣的問題。分析 apm 的處理流程,懷疑是在關機前驅動程序沒有正確處理 apm 發出的詢問消息造成的。由于部分驅動程序沒有源代碼,決定 hack 掉 apm.c 的關機部分,讓兩種方式的關機走同樣的流程。于是把 apm.c 的 check_events 函數中對 APM_SYS_SUSPEND 部分改寫為如下代碼:
ret = exec_usermodehelper(poweroff_helper_path, argv, envp); if (ret) { printk(KERN_ERR “apm.c: failed to exec %s , errno = %dn”, poweroff_helper_path, errno); } break;
定義了一個用戶態應用程序 poweroff_helper_path,當 POWEROFF 鍵按下的時候系統運行這個 kernel_helper 程序。我們再寫一個通過 sys_reboot 系統調用關機的程序,放在指定的位置下。死機的問題就解決了。
2) 快速返回實模式重啟
主要可以參考了 process.c 中的返回實模式的代碼,比如我把 real_mode_switch 換成如下代碼:
// For fast reboot support static unsigned char fast_reboot_switch [] = { 0x66, 0x0f, 0x20, 0xc0, /* movl %cr0,%eax */ 0x66, 0x25, 0x10, 0x11, 0x11, 0x11, /* andl $0x11111110,%eax */ 0x66, 0x0f, 0x22, 0xc0, /* movl %eax,%cr0 */ 0xea, 0x00, 0x00, 0x00, 0x70 /* ljmp $0x7000,$0x0000 */ };
系統就可以切換到實模式中,然后跳轉到 7000H:0 位置開始執行。
6. ACPI 概述
在 2.4.20 內核中 ACPI 模塊被注明為試驗和未完成,里面有一部分功能也許沒有實現。如果 APM 和 APCI 兩個模塊同時編譯進內核,APM 在 ACPI 前被加載,APM 起作用使 ACPI 退出。對于系統電量、電源實踐一類的支持(主要是在筆記本上有用),靠的是 acpid 這個 daemon 程序。
沒有一個功能類似 apm 的應用程序切換狀態,acpi 的程序僅僅完成了對 acpi 狀態的查詢。用戶實現 S0-S4 的功能可以直接向 /proc/acpi/sleep 文件中寫入數字來實現。通過讀出 (cat) 其中的內容可以知道系統到底支持那些模式。
acpi 模塊的源代碼主程序在 linux/drivers/acpi/driver.c 中,如果向 sleep 文件寫東西,就轉到了 linux/drivers/acpi/ospm/system/sm_osl.c 文件的 sm_osl_proc_write_sleep 函數中,這個函數后來調用了 sm_osl_suspend 函數。在這個函數里完成了各種功能,包括保護各種狀態。最后真正的 sleep 是通過對 acpi_enter_sleep_state 的調用完成的,這個函數在 Linux /drivers/acpi/hardware/hwsleep.c 文件中,這里寫了 acpi 的寄存器使系統進入 sleep 狀態。寫寄存器的指令在這個目錄下面的 hwregs.c 中。
7. 總結
本文對 acpi 的介紹非常簡略,實際上 ACPI 必定會成為將來 Linux 內核中首選的電源管理方式。由于目前官方代碼中 ACPI 版本較低,所以沒有太詳細的論述,希望將來的內核能有所改進。
?
下載該資料的人也在下載
下載該資料的人還在閱讀
更多 >
- Android 源碼添加長按電源鍵重啟功能
- linux 從入門到跑路-電源管理
- ideapad720s在接通電源情況下,關機后自動重啟的解決辦法
- Mac電腦選擇系統菜單中的關機或重啟無法關機或重啟,只能通過按電源鍵關機以及打開應用經常卡死問題及解決方案
- [Linux] Ubuntu電源鍵軟關機設置
- 嵌入式Linux系統重啟后如何使得redis中的數據不再有
- 【嵌入式Linux(基礎篇)】嵌入式Linux底層系統開發流程和應用開發流程
- 嵌入式Linux專題(一)——嵌入式Linux系統構成及啟動流程
- 嵌入式 Linux 啟動流程和 bootloader 介紹
- STM8S單片機入門:關機模式開關機按鈕資料下載
- 如何實現遠程FPGA的更新和重啟 21次下載
- 嵌入式Linux與物聯網軟件開發C語言內核深度解析書籍的介紹
- halt poweroff reboot問題 0次下載
- 精彩易懂的LINUX講座 0次下載
- 基于ARM9的嵌入式Linux開發流程的研究
- python解析netflow數據到csv的流程詳解 516次閱讀
- 定時開關機在哪里設置 定時開關機對手機有利還是有害 6415次閱讀
- centos關機和重啟命令 883次閱讀
- Linux系統文件讀寫流程 597次閱讀
- kernel panic流程分析 893次閱讀
- Linux發送HTTP網絡包圖像 sk_buff數據結構解析 2105次閱讀
- 一文解析鴻蒙LiteOS和LINUX比較 2.1w次閱讀
- 蘋果手機經常死機或自動重啟應該如何解決 5.4w次閱讀
- 單片機自關機電路原理圖 5187次閱讀
- 手機重啟和關機再開機到底有什么區別? 1.1w次閱讀
- 嵌入式Linux OS啟動流程 3638次閱讀
- 一文解析鈷酸鋰生產工藝流程 1.8w次閱讀
- 詳解bootloader的執行流程與ARM Linux啟動過程分析 1w次閱讀
- 自動關機電路,自動關機原理分析 1.7w次閱讀
- 超詳細電腦加速關機100%絕技!教你幾招電腦關機慢的解決方法 4.5w次閱讀
下載排行
本周
- 1TC358743XBG評估板參考手冊
- 1.36 MB | 330次下載 | 免費
- 2開關電源基礎知識
- 5.73 MB | 6次下載 | 免費
- 3100W短波放大電路圖
- 0.05 MB | 4次下載 | 3 積分
- 4嵌入式linux-聊天程序設計
- 0.60 MB | 3次下載 | 免費
- 5基于FPGA的光纖通信系統的設計與實現
- 0.61 MB | 2次下載 | 免費
- 6基于FPGA的C8051F單片機開發板設計
- 0.70 MB | 2次下載 | 免費
- 751單片機窗簾控制器仿真程序
- 1.93 MB | 2次下載 | 免費
- 8基于51單片機的RGB調色燈程序仿真
- 0.86 MB | 2次下載 | 免費
本月
- 1OrCAD10.5下載OrCAD10.5中文版軟件
- 0.00 MB | 234315次下載 | 免費
- 2555集成電路應用800例(新編版)
- 0.00 MB | 33564次下載 | 免費
- 3接口電路圖大全
- 未知 | 30323次下載 | 免費
- 4開關電源設計實例指南
- 未知 | 21548次下載 | 免費
- 5電氣工程師手冊免費下載(新編第二版pdf電子書)
- 0.00 MB | 15349次下載 | 免費
- 6數字電路基礎pdf(下載)
- 未知 | 13750次下載 | 免費
- 7電子制作實例集錦 下載
- 未知 | 8113次下載 | 免費
- 8《LED驅動電路設計》 溫德爾著
- 0.00 MB | 6653次下載 | 免費
總榜
- 1matlab軟件下載入口
- 未知 | 935054次下載 | 免費
- 2protel99se軟件下載(可英文版轉中文版)
- 78.1 MB | 537796次下載 | 免費
- 3MATLAB 7.1 下載 (含軟件介紹)
- 未知 | 420026次下載 | 免費
- 4OrCAD10.5下載OrCAD10.5中文版軟件
- 0.00 MB | 234315次下載 | 免費
- 5Altium DXP2002下載入口
- 未知 | 233046次下載 | 免費
- 6電路仿真軟件multisim 10.0免費下載
- 340992 | 191185次下載 | 免費
- 7十天學會AVR單片機與C語言視頻教程 下載
- 158M | 183278次下載 | 免費
- 8proe5.0野火版下載(中文版免費下載)
- 未知 | 138040次下載 | 免費
評論
查看更多