淘气的程序员:Linux之父雕刻在Linux内核中的故事
本文内容由公众号“格友”原创分享
1、引言
由于LINUX操作系统的流行,Linus 已经成为地球人都知道的名人。尽管大家可能都听过钱钟书先生的名言:“如果你吃个鸡蛋觉得味道不错,又何必认识那个下蛋的母鸡呢?” 但是假如真是遇到一个“特别显赫”的鸡蛋,很多人还是想看看能生出这颗神蛋的母鸡的,或者者想听听这只母鸡的故事。
其实,在Linux内核的代码里,就隐藏着关于Linus大神的少量美妙故事
2、代码中隐藏着“feel dead”这句话
启动Linux系统,Ctrl + Alt + T打开一个终端窗口,执行如下命令,唤出GDB,并打开形容内核空间的kcore虚拟文件:
$ sudo gdb –core /proc/kcore
而后在GDB中执行如下命令加载内核的符号信息:
(gdb) file /home/ge/work/linux-3.12.2/vmlinux
再切换为INTEL风格的反汇编:
(gdb) set disassembly-flavor intel
接下来反汇编用于系统重启的SYSC_reboot内核函数:
(gdb) disassemble??SYSC_reboot
结果相似下图所示:
对于看到汇编就晕的看官勿要急(^_^),其实x86汇编是非常简单易懂的,特别是这个函数很好了解,里面充满着故事。另外,这可是地地道道Linus大神所写的代码啊。
在这个函数里有一串比较指令,有理且有趣。不妨先看这一句:
cmp DWORD PTR [ebp-0x114],0xfee1dead
这个常量很酷吧?Feel Dead(中文直译就是“感觉要死了!”)。Linus大神是著名的语言大师,常常语出惊人,用非常简短的语言说出人间真善美,说出他人所不敢说。由于这个函数是用来重启的,假如不feel dead,干嘛要重启呢?
3、Linus大神的生日也藏在了代码中
再往下看,会看到这样一条比较指令:
cmp? ? edi,0x28121969
这个常量是不也很特别,0x28121969,是不很像是日期,对的,这就是Linus大神的出生年月日:1969年12月28日。
明年,Linus大神50岁了,时光如流水啊,当年的毛头小伙,就要50岁了。三十而立,四十不惑,五十而知天命。Linus大神显然提前完成了“知天命”的目标。他就是上天派下来革Windows的命的。(^_^)
4、Linus大神把一家人都藏在代码里了
再往下看,还有一个日期:
cmp? ? edi,0x5121996
1996年12月5日,这个日期是什么呢?是Linus大女儿的生日。
把时光倒退回1993年,那时Linus还是24岁的棒小伙,应该是大学毕业不久吧,当时知道Linux的还不多。有一天,Linus亲身授课,宣传Linux的用法。课程结束时,Linus留了一个课后测验,要求参与者做好了以邮件形式交卷。结果,有一位上课的美女在交测验结果的同时向Linus发出了一个约会的邀请,于是一场培训成就了一段美妙的姻缘,这个女生(Tove)成了Linus的太太。值得一提的是,Linus太太武功高强,曾经6次夺得芬兰国家级别的跆拳道比赛冠军。
1997年6月,第二届亚特兰大Linux展现会(Atalanta Linux Showcase,简称ALS)在美国举行,这是Linux发展早期的一个年度盛会。在周五晚上的感谢晚宴上,Linus全家出席,在会议的相册中,可以看到幸福的一家人。
照片来自http://linuxshowcase.org)
照片中,Tove深情地看着Linus。Linus抱着的就是他们的大女儿,名叫Patricia Torvalds。Linus把她称作Linus v2.0。在位于母校网站的一个个人主页上(https://www.cs.helsinki.fi/u/torvalds/),Linus放了几张Patricia婴儿时的照片,至今仍在,好久没有升级了。从网页上的信箱(torvalds@transmeta.com)来看,当时Linus还没有全职做Linux,还在Transmeta公司工作。
(照片来自https://www.cs.helsinki.fi/u/torvalds/)
2015年8月,opensource.com特别采访了已经在读大学的Patricia(报道地址:https://opensource.com/life/15/8/patricia-torvalds-interview)。报道提到,Patricia酷爱计算机科学,已经在多个IT公司实习,技术方面小有成就,大有子承父业的雄心壮志。
(照片来自opensource.com)
照片中站在中间便是Patricia,她旁边的另两个年轻女生是她的两个妹妹,她们的生日也可以在上面的汇编代码里找到:
cmp? ? edi,0x16041998
cmp? ? edi,0x20112000
一位是98年,一位是00后。
5、那么,这些神秘的常量是如何用的呢?
这要看一下reboot API的函数原型:
int reboot(int magic, int magic2, int cmd, void *arg);
在这个API的文档中(man reboot(2)),可以看到关于上述常量的说明:?
This system call will fail (with EINVAL) unless magic equals LINUX_REBOOT_MAGIC1 (that is, 0xfee1dead) and magic2 equals LINUX_REBOOT_MAGIC2 (that is, 672274793).? ?However, since??2.1.17??also??LINUX_REBOOT_MAGIC2A??(that??is,??85072278) and since 2.1.97 also
LINUX_REBOOT_MAGIC2B (that is, 369367448) and since 2.5.71??also??LINUX_REBOOT_MAGIC2C (that??is,??537993216)??are permitted as value for magic2.??(The hexadecimal values of these constants are meaningful.)
括号里的一句说这些常量的十六进制是富有含义的,固然。
换句话来说,要想成功调用reboot API,那么前两个参数必需严格按如下规则填写:
1)第一个参数必需是0xfee1dead;
2)在Linus大神的大女儿Patricia出生之前,第二个参数能且只能是0x28121969,也就是大神的生日;
3)当Linus有了大女儿Patricia后,第二个参数也可以是Patricia的生日0x5121996。这样说有点不准确,准确的说法是从Linux内核2.1.17版本开始,第二个参数也可以是0x5121996。查阅kernel.org上的内核;4)发布历史,2.1.17应该发布于1996年12月22日。可以想见,Linus大神在喜得爱女的几天内就修改了内核代码,而后在女儿满月之前把把这个代码发布给世界了;
5)当Linus有二女儿后,第二个参数也可以是二女儿的生日;
6)当Linus有了小女儿后,第二个参数也可以是小女儿的生日。
在内核代码中,上述规则是在reboot.c中强制的,代码如下:
/* For safety, we require “magic” arguments. */
if(magic1 != LINUX_REBOOT_MAGIC1 ||
????????????????(magic2 != LINUX_REBOOT_MAGIC2 &&
????????????????magic2 != LINUX_REBOOT_MAGIC2A &&
????????????????magic2 != LINUX_REBOOT_MAGIC2B &&
????????????????magic2 != LINUX_REBOOT_MAGIC2C))
????????return-EINVAL;
这个for safety,有点含糊啊!哈哈。
由于应用程序调用这个系统服务的时候必需使用这一系列常量,由于它们的定义写在uapi目录下的reboot.h,即:
/* ?* Magic values required to use _reboot() system call. ?*/ #define??????? LINUX_REBOOT_MAGIC1??????? 0xfee1dead #define??????? LINUX_REBOOT_MAGIC2??????? 672274793 #define??????? LINUX_REBOOT_MAGIC2A??????? 85072278 #define??????? LINUX_REBOOT_MAGIC2B??????? 369367448 #define??????? LINUX_REBOOT_MAGIC2C??????? 537993216
注意啊:在这个文件和文档中,代表生日的四个常量都是以十进制表达的,应该是为了隐藏一下秘密吧。
0:000> .formats 0n85072278
Evaluate expression:
Hex:???? 00000000`05121996
如此看来,Linus大神不仅把这些常量写在Linux内核代码中,而且使它们成为Linux API的一部分。这意味着,这将成为永远。只需Linux系统还在,那么这些常量就将永远使用,由于API意味着客户态和内核态的法定接口。为了保障应用程序的兼容性,不可轻易变化。
6、写在最后
无论哪种文化,家庭都有着极其重要的地位。修身齐家治国平天下,欲治其国者,先齐其家。从上面的故事来看,Linus大神是个很爱家的男人。他把自己心爱的家庭成员生日铭记(雕刻)在了他的伟大作品之中。
那么,Linus大神为什么选择reboot系统调用呢?reboot代表着新的开始,代表不拘泥于现状,从新出发,从头再来。这是很多人都喜欢的人生哲学。在古老的易经中,第63卦是既济,字面意思是渡河成功,代表成就了一个目标。但这并不是终结,最后一卦(第64卦)是未济,代表还有新的目标没有达到,需要继续努力。
某种程度上来说,人生应该在实现一个个“既济”的成果之后,不断地向着“未济”的目标进军。这也意味着人生要不断学习,用《荀子》一书开篇的话来说就是“学不可以已(中止)”。
这篇短文是带着对Linus大神的敬意来写的,希望大家受到鼓舞,学习Linus爱家爱代码的敬业精神
感谢阅读
对高端程序员的要求,不是精通某一门语言或者者某一个平台,而是工程能力/处理问题的能力。换言之,你应该针对项目提出处理方案,而后为处理方案寻求最好的工具,而这些工具可能是你用过的也有可能是没用过的,假如没用过,这不能成为你避开该工具的理由。如此说来,强调自己是“某语言程序员”将会过时,替代的说法是“全栈”。
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 淘气的程序员:Linux之父雕刻在Linux内核中的故事