为什么你应该学习 Linux
Note: 本文的目标读者是计算机专业学生和希望深入了解计算机的朋友们。
今天参加了微软学生夏令营的 Windows Azure Camp,大约从下午 16:00 到晚上 21:30。共有10个队,每个队分为四组,其中 Coding 组有必做题和选做题。必做题是,在 Windows Azure 云平台上,搭建一个 Web 应用,用户上传图片,把图片旋转后显示给用户,并保存到云存储上。选做题是,把用户上传的原图和旋转后的图片拼成一张图片。(我没有听题,可能不准确,见谅)
我没有在自己的队里工作,而是在场里四处乱转,跟各队选手聊聊天,看大家都在干什么。初看起来,似乎有点像 ACM 的赛场。
首先澄清一点,上图中不是所有的人都在 Coding 组,大部分人的任务本来就不是编程序。每个队的 Coding 组是 3~7 个人,有的队并不在场里编程。
第一个现象:很多 Coding 组的人竟然没带笔记本电脑。这让我想起 LUG 每周小聚,大多数人两手空空来听技术讲座,没有动手操作,结果就像听耳旁风一样。国内高校的计算机教育以理论教学和笔试为主,上机实验往往是蒙混过关,因此很多计算机专业的学生没有养成动手操作的习惯。
第二个现象:不会查找技术文档。现场有不少人盯着 Visual Studio 界面“若有所思”,上前一问,才知道是因为不会用 API,或者 API 不像预想的那样工作。绝大部分人倒是知道百度一下,Bing 一下,或者 Google 一下,不过大多是用中文去搜索,搜索结果大多是 CSDN 上的,质量可想而知。他们把搜到的代码粘贴进去,好不容易修正了语法错误,发现不 work,就一筹莫展了。
记得刚来 MSRA 的时候,著名博主刘未鹏做过一个报告,说我们要只读精挑细选的好书和好文章,保证信息来源的质量;英语应该是全世界程序员的第一语言,而不是第二语言。我想,每位有志于成为程序员的同学,都应该学会查找技术文档。
- 尽量用英文,在国际化的搜索引擎里查找;
- 优先阅读官方 API 文档,发现官方文档没有解释清楚的时候再寻求非官方资料的帮助;
- 鉴别质量高的技术讨论站点,比如 StackOverflow、MSDN。
第三个现象:不会使用调试工具。这个问题我在学校的实验课上就已经发现,同学们大多是 printf 党。这次的活动可难倒 printf 党了,Web 界面,往哪里 printf 呢?当然,可以往 Web 页面上输出信息,或者用 VS 的 TRACE 输出到调试窗口里。不过即使是 printf,也是有技巧的,比如用“二分法”定位出错位置。事实上,VS 内置了强大的断点调试功能,在某个地方断下来之后,鼠标悬浮到变量上面,就能显示出变量的值,复杂对象还能以结构化的方式显示出来。这种方便程度是 Linux 下的 gdb 也难以望其项背的。
转了几圈之后,我陷入了沉思。微软以丰厚的奖学金在各知名高校评选“微软小学者”,还花了不少人力物力组织起微软学生俱乐部,这次活动就是微软邀请小学者和俱乐部的同学参加。一个合理的推测是,来参加活动的同学代表了计算机水平相对较高的高校学生。然而,活动现场却完全没有 ACM 的气氛。
吐槽了这么多,似乎跟本文标题“为什么你应该学习 Linux”没有关系啊。下面就进入正题。
Windows 操作系统是面向最终用户(end-user)的,把很多普通用户不需要知道的技术细节都封装起来了。基于商业上的考虑,Windows 软件的开发商也不太可能公开太多技术内幕。我们即使想了解其内在原理,也只能从其外部行为管中窥豹。因此我十分敬佩研究 Windows 的黑客们,他们用反汇编和调试工具硬是把已经去掉符号和语义信息的机器码搞明白了,我可是一点也搞不来。
Linux 系统准确地说是 GNU/Linux 系统,Linux 是操作系统内核,GNU 项目提供了一套用户态的工具链,合起来就是 GNU/Linux 自由操作系统了。“自由”软件的特征之一就是开源,也就是软件的源代码可以自由取得。这就为我们学习和研究软件的运行原理提供了方便。
GNU/Linux 系统还继承了 UNIX 系统的工具链,每种工具像是瑞士军刀,通过命令行选项和“管道”的组合,能够表达出指数级别的可能性。这使得一行 shell 脚本所能完成的事可能超过很多行C代码。这种“轻松编程”还孕育了“黑客文化”,也就是不把编程看作一种“居庙堂之高”的严肃过程,而是作为解决日常问题的一种手段——本身就是半天搞定的事,何必编写文档、制定开发计划呢?
因此,Linux 系统是各种开源编程语言的首选平台(我认为官方编译器由开源社区维护的就算是开源编程语言),Python、Ruby、Node.js、Haskell、PHP 等开源语言的首选平台都是 Linux。这些语言与 C、C++、Java 等语言相比,最直观的特点就是 “Hello World” 只需要一行,更本质的特点是这些语言的抽象能力更强。学会了这些语言,就像是小孩学会了表达抽象概念的词语,能够更简练、更符合直觉地表达相对复杂的编程模型和数据结构。即使是在使用 C 之类的传统语言时,也能把这些相对高级的结构用作更复杂软件的 building block。
由于开源社区的分享文化,这些开源语言都有很多开源库(library),很有可能世界那头的某个爱好者早已解决了困扰你很久的问题,并把解决方案无私地分享出来了。这种分享让社区中的每个人站在前人的肩膀上,快速进步。
我不会像王垠那样鼓吹“完全用 Linux 工作”。事实上我现在的桌面环境是 Windows,因为我实在不愿意折腾那些支持不完整的驱动、bug 一箩筐的桌面环境、Windows-only 的应用软件。编程序的话,自己用的就在 cygwin 里编写、调试和运行;需要图形界面的就在 vim 里写,在 Visual Studio 里编译和调试(据说 VS 有仿 vim 插件,我还没尝试)。主要没有适应的就是网络配置和进程管理,目前我还没找到像 Linux 那么顺手的工具。等我摆脱屌丝了,再看看 Mac 这个源于 UNIX 又注重用户体验的系统是不是能兼有 Windows 和 Linux 的优势。
不论日常的工作环境是何种操作系统,我都强烈建议计算机专业学生和希望深入了解计算机的各路朋友去学学 Linux,了解操作系统和各种应用软件背后的原理,把写代码当成一种习惯,学会查找技术文档和使用调试工具。
最后,分享一个与 Azure Camp 那个题有点类似的思考题:搭建一个 Wifi 热点,让邻居家蹭网的人显示的图片是 upside down 的,而自己看到的图片正常。
这个问题我最早是在某本讲极客文化的书里看到的,没想到网上已经有人写过解答了(看起来这文章年代挺久远的):
http://www.ex-parrot.com/pete/upside-down-ternet.html
不过,这个修改 URL 的方法只针对 HTTP 有效,HTTPS 由于是加密传输,是无效的。可喜的是,大部分 HTTPS 网站的静态图片一般是通过 CDN 分发的,而 CDN 一般是走 HTTP 的(不加密)。因此,检测 HTTP 头,将 Content-Type 为 image 的图片拦截下来,经过 upside down 处理后再发给用户,也许可以做得更彻底。