当感觉已麻木,告诉 Linux 说reboot

偶然看到一篇台湾同行写的blog,挺有意思的转过来看看!!


當感覺已麻木,告訴 Linux 說 reboot


這標題是前幾日在 twitter 上意外聯想到,對於 Linux reboot() 系統呼叫的 geek 笑話,為了解釋箇中的幽默,決定寫一篇短文。

當我們查閱 reboot(2) 的 manpage 時,可發現其函式宣告如下:
/* Under glibc some of the constants involved have gotten
   symbolic names RB_*, and the library call is a 1-argument
   wrapper around the 3-argument system call: */

#include <unistd.h>
#include <sys/reboot.h>

int reboot(int cmd);
至於參數的 "cmd",就是以 RB_ 開頭巨集表示的數值,可為以下:
  • RB_AUTOBOOT - 系統會列印 "Restarting system.",並立即重開
  • RB_HALT_SYSTEM - 系統會列印 "System halted.",接著將控制權交與 ROM monitor (在非 x86 的系統很常見)
  • RB_ENABLE_CAD - 驅使 CAD (Ctr-Alt-Del 組合按鍵) 生效,亦即按下 CAD 後,就執行前述 RB_AUTOBOOT 的動作
  • RB_DISABLE_CAD - 使 CAD 失效,這意味著 CAD 不會讓系統重新啟動,但會觸發 SIGINT signal 並遞送給 init (process 1)
這是 glibc 考量到支援的眾多平台,做了一些包裝,所以 reboot() 在 glibc 是以接受單一參數的函式存在。在早先的版本,就是直接提供 Linux kernel 的系統呼叫 wrapper,其描述如下:
/* For libc4 and libc5 the library call and the system call
   are identical, and since kernel version 2.1.30 there are
   symbolic names LINUX_REBOOT_* for the constants and a
   fourth argument to the call: */

#include <unistd.h>
#include <linux/reboot.h>

int reboot(int magic, int magic2, int cmd, void *arg);
看到參數的 magic 與 magic2 字樣,很自然就會想到,就是 magic number,並且背後大有文章。在資訊技術的領域中,不乏會有透過有限空間,表達獨特趣味的手法,比方說 Microsoft COM 技術裡頭,不時會有蹦蹦跳跳的貓咪,證據就是 "MEOW packet",據某個權威者的說法 MEOW 代表 "Microsoft Extensible Object Wire" 之意,但不免啟人疑竇。又,從 Oak (橡樹) 更名為 Java 的知名程式語言,其 classfile 開頭就是 Cafe Babe (表示法為 0xCAFEBABE,亦即「咖啡寶貝」),這一類的案例更是豐富,凡十六進位表示法恰好能對應到英文某些詞彙者,就稱為 [ Hexspeak]。Linux kernel 內自然也有,而且不只一處,本文的主題 reboot() 就堪稱其中經典。

前述的函式宣告中,前兩個參數 (magic 與 magic2) 必須同時符合某個條件,才真正會觸發系統重新啟動或設定 CAD 行為的能力,以避免不當地使用。明確來說,magic 必須為 LINUX_REBOOT_MAGIC1 ("0xfee1dead"),而 magic2 的值要為以下其中一個: (定義於標頭檔 include/linux/reboot.h 之中)
  • LINUX_REBOOT_MAGIC2 = 672274793
  • LINUX_REBOOT_MAGIC2A = 85072278 (Linux 2.1.17 追加)
  • LINUX_REBOOT_MAGIC2B = 369367448 (Linux 2.1.97 追加)
  • LINUX_REBOOT_MAGIC2C = 537993216 (Linux 2.5.71 追加)
LINUX_REBOOT_MAGIC1 的值實在有意思,"0xfee1dead" 不就形如 "feel dead" 嗎?差別是前者是數字 "1",後者是小寫字母 "l",英文中 dead 的意思可解釋為「麻木不仁」一類,這也是本文標題的來源,因為,這會帶入 reboot() 作呼叫的動作,當然,看倌要發揮一些 geek 的幽默。

不過,趣味處不只如此,magic2 四個數字貌似平凡,但實際上述說了 Linux Kernel 發展的歷史,怎麼說呢?咱們用比較技巧性的方式分析,首先是 LINUX_REBOOT_MAGIC2 = 672274793,看看其十六進位表示法:
$ printf "%x\n" 672274793
28121969
稍微作切割,就是 28/12/1969,也就是 Linus Torvalds 生日的 DD/MM/YYYY 寫法。也可以這樣解讀:
$ perl -e 'print localtime(672274793). "\n";'
Mon Apr 22 06:59:53 1991
透過 localtime 得知筆者在 GMT+0800 (台北時區) 的日期表示,這個 1991 年四月 22 日大致是 Linus Torvalds 當年在芬蘭赫爾辛基大學撰寫 Linux Kernel 的日期。令人拍案叫絕之處,還不只如此,咱們繼續看下一個 LINUX_REBOOT_MAGIC2A = 85072278:
$ printf "%x\n" 85072278
5121996
同樣的手法,得知日期是 1996 年十二月 5 日,這天是 Linus 千金 Patricia Miranda Torvalds 出生的日子,也被稱為 "Linus v2.0",同理可推論下個數值 LINUX_REBOOT_MAGIC2B = 369367448:
$ printf "%x\n" 369367448
16041998
日期 1998 年四月 16 日,也就是二千金 Daniela Yolanda Torvalds,或 "Linus 3.0" 誕生的日子,當時甚至有網友異想天開問說「Linus 3.0 是否支援 IPv6 」或「Linus 是否 GPL 自己 的 DNA 序列」等令人莞爾的問句,女兒出生隔日則推出 Linux 2.1.97。

「最新」的一個家庭成員,表示為 LINUX_REBOOT_MAGIC2C = 537993216::
$ printf "%x\n" 537993216
20112000
小女兒 Celeste Amanda Torvalds 誕生於 2000 年十一月 20 日,陪伴著服務於幼稚園的夫人,一家五口,應該頗熱鬧。看來沈迷電腦技術的高人,不僅軟體生產力強大,真實世界也不遑多讓。該不會過一段時間,又追加一個 magic number 呢? *笑*

在 uClibc 中,關於 reboot() 函式的實做,可窺知如何使用系統呼叫。檔案 libc/sysdeps/linux/common/reboot.c 的內容如下:
#include <sys/syscall.h>
#include <sys/reboot.h>
#define __NR__reboot __NR_reboot
static inline _syscall3(int, _reboot, int, magic, int, magic2, int, flag);

int reboot(int flag)
{
        return (_reboot((int) 0xfee1dead, 672274793, flag));
}
reboot() 系統呼叫要能呼叫,其成立條件除了前述的 magic 與 magic2 要符合外,系統得有 SYS_BOOT capability (參見 include/linux/capability.h 標頭檔) 以及 BKL (Big Kernel Lock,就最新的發展來說,已逐漸移去 BKL)。除了字面上 "reboot" 的「重新啟動」意思,事實上,這個系統呼叫 (核心實做名稱為 "sys_reboot") 提供以下功能選項:
  • 指定方式關機:restart (重新啟動/暖開機)、halt (系統停止運作)、poweroff (關閉電源)
  • 觸發某些硬體架構上特定的「關機指令」,比方說回到 watchdog 或 ROM monitor
  • 切換 CAD (control-alt-delete) 的處理
為了讓核心的驅動或運作得以正常結束,reboot 系統呼叫也會逐一觸發已註冊的 reboot_notifier callbacks。

談及 reboot 系統呼叫時,我們也會提到 Linux 上的 [ SysRq],透過這個神奇的機制,我們可要求系統作些特別的動作,如重新啟動系統或關機。首先得先使其生效:
# echo 1 > /proc/sys/kernel/sysrq
強制重新開機 (也叫做 fast reboot) 就給予以下指令:
# echo b > /proc/sysrq-trigger
至於強制關機,就是以下:
echo o > /proc/sysrq-trigger

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值