說(shuō)到在 linux 下的編程,很多人會(huì)想到用C語(yǔ)言,Linux 的內(nèi)核、shell、基礎(chǔ)命令程序,也的確是用C語(yǔ)言編寫(xiě)的,這首先證明了一點(diǎn),C語(yǔ)言很強(qiáng)很通用。
到目前為止,C語(yǔ)言依然壟斷著計(jì)算機(jī)工業(yè)中幾乎所有的系統(tǒng)編程,而且也正因?yàn)槭荂語(yǔ)言,才使得 Unix 以及后來(lái)的 Linux 能夠這么廣泛地被人們?nèi)パ芯俊⑷ジ倪M(jìn)、去制作自己的分支,以至于我們能在各種硬件平臺(tái)上使用它們。
但是細(xì)心的人會(huì)發(fā)現(xiàn),Linux 啟動(dòng)過(guò)程中所涉及的各種程序,很少有C語(yǔ)言的痕跡。它們大多是腳本程序。不單單在啟動(dòng)過(guò)程中是這樣,那些用于安裝軟件的工具 yum、apt-get,甚至是 configure 和 Makefile 也都是腳本程序。而且你可能還沒(méi)注意到,那些用于系統(tǒng)管理的工具,如配置 ADSL 撥號(hào)上網(wǎng)的工具、配置守護(hù)進(jìn)程的工具等,很多也都是腳本程序。
大量使用腳本程序,是所有類(lèi) Unix 系統(tǒng)不同于其他系統(tǒng)的一個(gè)顯著特征,催生人們?cè)?Linux 中大量使用腳本來(lái)編寫(xiě)程序,并不僅僅是因?yàn)槟_本對(duì)人直觀、容易修改這種顯著特性所決定的。另外一個(gè)主要的原因就是 Linux 所支持的腳本語(yǔ)言種類(lèi)十分豐富。
所有類(lèi) Unix 系統(tǒng)所必備的 shell,其本身就是一個(gè)強(qiáng)大的腳本解釋器。所以從 shell 誕生的那一天起,shell 就是那些不懂 C 語(yǔ)言,又必須在 Unix 上編寫(xiě)程序的用戶(hù)們的首選工具。
這就給了人們一種新的選擇,使用 shell 編程不用去理會(huì)讓人頭暈的指針;shell 程序可以直接利用系統(tǒng)命令來(lái)完成一些需要用大量 C 代碼的功能;shell 編程不用去理會(huì)數(shù)據(jù)類(lèi)型,不用考慮煩人的數(shù)值和字符數(shù)據(jù)的轉(zhuǎn)換問(wèn)題;shell 程序同樣提供順序、選擇分支和循環(huán)這三種能夠構(gòu)建任意算法的基礎(chǔ)設(shè)施。因此,shell 很快就能夠被非專(zhuān)業(yè)用戶(hù)所接受、掌握,并編寫(xiě)出非常實(shí)用的程序。
隨著時(shí)間的推移,這些非專(zhuān)業(yè)用戶(hù)想往更高的方向發(fā)展,遇到了一些 shell 處理起來(lái)會(huì)很“蹩腳”的問(wèn)題,比如分析文本和修改文本(別忘了“萬(wàn)般皆文本”)。這個(gè)時(shí)候他們會(huì)發(fā)現(xiàn) 有 awk 和 sed。也只需要寫(xiě)幾行腳本就能將這些問(wèn)題處理得很好。而且它們也跟 shell 配合得天衣無(wú)縫。或許這個(gè)時(shí)候會(huì)覺(jué)得加入了 awk 和 sed 的 shell 腳本有些難看,不過(guò)沒(méi)關(guān)系,還有 Perl 和 TCL。Perl 天生就是為處理文本而存在的,TCL 也不含糊。
如果覺(jué)得這些語(yǔ)言都太老氣了,有些過(guò)時(shí)了,不要緊,還有 Python、Ruby 等這些現(xiàn)代腳本語(yǔ)言,它們除了不能寫(xiě)操作系統(tǒng)內(nèi)核之外,幾乎什么都能干,而且還是面向?qū)ο蟮摹?/span>
不管怎樣,在 Linux 下能夠選擇的腳本語(yǔ)言都是極其豐富的。它們最大的特點(diǎn)就是簡(jiǎn)單、好學(xué)且資料豐富。簡(jiǎn)單就意味著容易維護(hù),好學(xué)就容易吸引用戶(hù),資料豐富就不會(huì)在解決 bug 上出現(xiàn)障礙。即便是專(zhuān)業(yè)的程序員,也會(huì)因?yàn)檫@些特點(diǎn)而特別偏好腳本語(yǔ)言,導(dǎo)致的一個(gè)結(jié)果就是腳本程序在 Linux 中的大爆發(fā)。
有讀者可能會(huì)問(wèn),為什么不選擇 C 語(yǔ)言呢?
C語(yǔ)言是 Unix 的母語(yǔ),這是毋庸罝疑的。前面也說(shuō)過(guò),正是因?yàn)橛辛薈語(yǔ)言,才使得 Unix 有了今天的成就。但為什么在 Linux 中有這么多程序,甚至是關(guān)鍵程序,不用C語(yǔ)言編寫(xiě)呢?
腳本程序由于是解釋執(zhí)行的,在執(zhí)行效率上自然是會(huì)有很大損失的。并且大家都知道,C語(yǔ)言所編寫(xiě)的程序又是以效率著稱(chēng)的。但是C語(yǔ)言是一種編譯型語(yǔ)言,要想讓C語(yǔ)言的程序能夠運(yùn)行,必須經(jīng)過(guò)編譯和鏈接這兩個(gè)步驟。
要知道,能夠?qū)⒂蓭资畟€(gè)源代碼文件構(gòu)成的C語(yǔ)言程序,有條不紊地編譯完成并能最終鏈接成一個(gè)可執(zhí)行程序,本身就是一件費(fèi)時(shí)又費(fèi)力的事情,如果一旦程序有問(wèn)題,還必須使用專(zhuān)門(mén)的調(diào)試工具一點(diǎn)點(diǎn)地去跟蹤判斷,修正之后再重復(fù)那些復(fù)雜的編譯和鏈接步驟,這又是一個(gè)極需技巧的事情。積累并掌握技巧又是一件費(fèi)時(shí)又費(fèi)力的事情。
在早些年,計(jì)算機(jī)性能不佳的時(shí)候,這些付出或許是值得的。但是放到現(xiàn)在,處理器的速度至少快了幾千倍,內(nèi)存大了幾千倍,硬盤(pán)甚至大了幾萬(wàn)倍,而價(jià)格卻更低了。從經(jīng)濟(jì)角度分析,機(jī)器的時(shí)間成本早己遠(yuǎn)遠(yuǎn)低于人的時(shí)間成本了。那么C語(yǔ)言在機(jī)器效率上的優(yōu)勢(shì)根本沒(méi)有任何意義。腳本程序能夠給人節(jié)省下來(lái)的時(shí)間成本,則更具經(jīng)濟(jì)效益。
要論機(jī)器效率,匯編語(yǔ)言比C語(yǔ)言要好上幾十倍,但是目前還有誰(shuí)在用匯編語(yǔ)言編程呢?
C語(yǔ)言在設(shè)計(jì)的時(shí)候,最主要的一個(gè)目標(biāo)就是能夠讓程序員自己處理內(nèi)存管理的問(wèn)題。這使得C語(yǔ)言很強(qiáng)大但又太過(guò)于靈活,導(dǎo)致了很多陷阱的出現(xiàn)。稍微一不注意,程序中就會(huì)存在難以發(fā)覺(jué)的 Bug,甚至是嚴(yán)重的安全漏洞。程序員們大多是要以時(shí)間或失敗為代價(jià)去積累經(jīng)驗(yàn),才能盡量避免這些問(wèn)題的發(fā)生。而且效率在大多數(shù)應(yīng)用中根本就不是問(wèn)題,首要的是正確。腳本程序的簡(jiǎn)單和直觀正是正確的起點(diǎn),C語(yǔ)言的靈活卻是錯(cuò)誤的根源。
但是,C語(yǔ)言并不是一無(wú)是處,也是 Unix 的精華。C語(yǔ)言作為通用程序設(shè)計(jì)語(yǔ)言是所向無(wú)敵的。C語(yǔ)言本身也非常簡(jiǎn)潔和緊湊,資料豐富且容易學(xué)習(xí)。C語(yǔ)言之后的少數(shù)語(yǔ)言設(shè)計(jì),為了不被C語(yǔ)言所吞并,不得不進(jìn)行大的改動(dòng),比如引進(jìn)垃圾回收機(jī)制等,以和C語(yǔ)言能夠在功能上保持足夠距離。也正是因?yàn)檫@樣,C語(yǔ)言始終沒(méi)有消失,只是它的光輝在 Linux 中稍稍地被腳本程序所遮擋了一下。
雖然效率并不是腳本程序的缺點(diǎn),但是種類(lèi)過(guò)于豐富卻是一個(gè)極大不足。編寫(xiě)一個(gè)復(fù)雜的應(yīng)用,往往很難使用一種腳本語(yǔ)言包桿到底,因?yàn)槟_本語(yǔ)言都有自己適用的場(chǎng)景,為了能夠快速有效地完成某個(gè)應(yīng)用,就需揚(yáng)長(zhǎng)避短,利用多種腳本語(yǔ)言混合編程。
多腳本語(yǔ)言的混合編程是一種知識(shí)密集型的編程方法,但不是編碼密集型的(這是能夠被普遍接受的原因)。為了能夠良好地使用這種方法,就要求程序員不僅僅要具備相當(dāng)數(shù)量的多種語(yǔ)言知識(shí),還必須具備能夠判斷這些語(yǔ)言的適用場(chǎng)景、以及如何將它們有效地組合在一起的經(jīng)驗(yàn)。
實(shí)際上,混合編程并不是腳本語(yǔ)言的專(zhuān)利,任何編程語(yǔ)言都行,只要你能找準(zhǔn)那些語(yǔ)言的特點(diǎn)。比如筆者就曾經(jīng)使用過(guò) Basic 和 C 進(jìn)行混合編程,去完成一個(gè) DOS 版萬(wàn)年歷程序。為了支持鼠標(biāo)點(diǎn)擊操作,用 C 完成了鼠標(biāo)中斷的處理。余下的部分都用 Basic 來(lái)完成。
在 Linux 中大量應(yīng)用腳本程序的場(chǎng)景,好多都是這種混合編程的典范。比如 Linux 的啟動(dòng)過(guò)程,主程序 init 是用 C 語(yǔ)言寫(xiě)的,具體到啟動(dòng)流程的各個(gè)環(huán)節(jié)則是 shell 腳本程序。
新聞熱點(diǎn)
疑難解答
圖片精選