零基礎編程入門(03)——操作系統與語言

零基礎編程入門(03)——操作系統與語言

53 人贊了文章

在上一章中,鄙人通過了對計算機起源的追溯,向大家解答了這幾個問題:

  • 什麼是計算機?有什麼用?從哪來?
  • 現代計算機的結構與起源
  • 進位、二進位與計算機指令

並帶大家領略了最原始的計算機,也就是所謂的『裸機』的一些相關知識。但是,裸機離我們目前所使用的功能複雜的個人多媒體計算機還有很長一段距離,所以在這章中,鄙人就將繼續向大家繼續講解我們計算機從『裸機』到現代個人電腦間的一些發展。

一、操作系統的誕生

在上一章中鄙人向大家講到了,馮諾依曼在對埃尼阿克提出改善意見時,提出了指令與程序存儲的概念,極大的簡化了當時人們操作計算機的複雜度。

然而,這一改善卻並沒有解決一個很關鍵的問題,一個什麼樣的問題呢?

就是當計算機進行運算時,必須要有人在旁進行操作,不停的將寫有指令程序的紙帶或磁帶輸入到計算機,然後等待計算結果。

舉個例子,當時的操作流程大致如下:

1、將記錄有程序一的紙帶輸入到計算機2、喝一杯咖啡3、再喝一杯咖啡...幾個小時後...n、喝第n-1杯咖啡n+1、計算機通知程序運行完成n+2、給計算機換上程序二的紙帶...接著喝咖啡...

所以,我們可以看到,在那個年代,操作計算機是一件非常苦逼的事情,在計算機運行程序的時候,操作人員除了看報紙和喝咖啡之外什麼事都幹不了,只能幹等在一旁,所以,顯然這樣的計算機操作方式是相當的低效。

然後到了1956年的某一天,美國商用機器公司(英文縮寫:IBM,如雷貫耳是不是)的一個名叫鮑勃·帕特里克的計算機操作人員在喝夠了咖啡後,痛定思痛,決心花點時間寫個小程序,這個小程序的功能很簡單,大致如下:

1、在計算機機載入了這個程序後,這個程序能使計算機按順序自動載入並運行後續載入的別的程序2、每個程序執行完,能按執行結果不同,決定下一步究竟該執行哪個程序,並可以將執行結果傳送給下一個程序

只要有了這兩個功能,他就不需要繼續長時間守候在計算機旁,不停的為計算機更換要執行的程序,而只需要一次性將需要執行的目標程序都載入到正在執行上述小程序的計算機上,就可以回家睡覺等第二天再來取結果了。

就這樣,他花了點時間完成了一個名為GM-NAA I/O的程序,而這個代碼極為簡單的程序,其蘊含的理念卻並不簡單,因為它正是我們公認的第一代操作系統(Operating System, 簡稱:OS)。

1964年,IBM公司發布了一台名為System/360的跨時代計算機,而該計算機正搭載了IBM基於GM-NAA I/O改良的一款名為OS/360操作系統。此計算機推出後,由於其實用的功能、簡便的操作、強大的性能與平民的價格,立即在全球各國引起了轟動,被世界上各大機構比如大學與企業所訂購,而世界也正是在這台計算機上,完成了計算機行業從軍用與科研到商用與民用的轉變,甚至至今在全球範圍內,依然有不少大型銀行的內部核心伺服器中依然存在大量的System/360系列的衍生計算機(在IBM工作過的應該比較熟悉)。

而類似GM-NAA I/O這樣的操作系統,在被人所熟知後,按其工作原理,將其稱之為批任務處理系統,即:可以進行批量任務處理的操作系統。

二、MULTICS與分時多任務系統

在批任務處理系統出現後不久,由於 System/360與一些其他的小型計算機(比如我們後面會提到的PDP系列)在商用與教科研領域的巨大成功,計算機行業得到了巨大的發展,大量民營機構加入到了計算機相關的研發工作。

1965年,由當時美國知名電話公司,美國貝爾電話公司下屬的貝爾實驗室(縮寫:AT&T)、美國麻省理工大學(縮寫:MIT)以及通用電器公司(縮寫GE:愛迪生與約翰摩根所建)共同開啟了一項研究。希望能共同開發一個新型的操作系統,名為:MULTICS,並在這個系統的研發過程中,提出分時與多任務這樣兩個概念,那什麼是分時與多任務呢?

在鄙人上述對於GM-NAA I/O系統的說明中,大家可以看到,它解決了人員在操作計算機時需要等候在計算機旁的問題。但是隨著計算機硬體運算速度的急劇上升,人們發現,一台計算機如果在一個時間內,只能處理一個人的計算任務,會顯得非常低效。

有的時候操作人員往往會希望一台計算機能同時解決多人的多個計算任務,而不同計算任務的緊急程度也是不同的,比如:

張三需要解決一個很棘手當天就要出結果不然就會被導師打屁屁的導彈彈道計算問題,於是帶著他剛編好程序,興沖沖的跑去了計算機實驗室,希望能佔下台機器立即把他的程序跑掉,然後就能回家吃飯睡覺打豆豆去了。

然而當他跑到實驗室後,卻發現早已有人捷足先登,唯一的一台計算機已經在運算李四的一些無關緊要的問題(諸如:星座與戀愛關係計算),更悲劇的是,那個任務要跑到明天才能有結果。。。於是唯有仰天長嘆,既生瑜何生亮。

所以,在出現了大量類似上述的慘劇後,科研人員逐漸意識到,他們需要一個新的操作系統,需要該系統能同時被多個人使用,並在同一時間內能同時進行多個運算任務,並能按任務緊急程度不同,為緊急的任務分配更多的計算機資源(運算時間)。

而這些需求,在MULTICS設計者眼中,簡單的講就是分時與多任務,所謂多任務就是指一台計算機能同時執行多個任務,然後CPU(上章說的中央處理器,控制器加上運算器,有印象了不?)能根據操作人員的指令,在不同的任務間進行切換執行。

比如在上述張三的慘劇中,如果是一台多任務系統計算機,那麼:

張三隻需要給李四打個電話,說明下情況,徵得同意後,通過手動輸入一個指令,中斷掉計算機當前正在執行的李四的運算任務。然後載入自己的任務程序去執行,直到執行完後,再輸入一個指令,讓計算機接著執行李四的任務,最後走人即可。

一場奪妻之仇引發的慘劇就此避免。

但是,我們可以發現一個問題,什麼問題呢?就是張三必須通過手動輸入中斷指令才能在兩個任務間進行切換,然而在某些不是非常緊急的情況下,張三希望能在載入自己的程序後就立即走人,讓自己的程序與李四的程序在一台計算機上同時進行運算,讓操作系統能自動按一定的時間,輪流執行兩個任務。

貝爾實驗室為了達成這種需求,於是又提出了一個叫做分時的概念。

所謂分時,就是指操作系統能讓計算機按一定的時間大小,自動在多個任務間進行輪換執行,並希望通過結合多任務的概念,使操作系統從此變得更為靈活。

然而,雖然想法是美好的,現實卻是殘酷的,最後,他們居然失敗了!

由於經費短缺與耗時過長,1969年,貝爾實驗室宣布退出了MULTICS項目的研發,所有參與到項目中的貝爾實驗室人員均被調回了貝爾實驗室,其中就有一位名為肯·湯普森 Ken Thompson的研究人員。

三、肯·湯普森與他的Unics

肯·湯普森在經歷過了 MULTICS 項目的洗腦後,卻被迫回到了貝爾實驗室,面對相比之下極為低效的批任務處理計算機,心中極為不甘。於是便一個人忙裡偷閒,在實驗室的庫房裡翻出來的一台廢棄的PDP-7小型機上,嘗試根據MULTICS自行開發一個新系統。

註:PDP-7是DEC公司(後併入康柏電腦)早期推出的小型計算機,至PDP-11達到巔峰。另需注意的是,此處『小型』是相對埃尼阿克這樣一間房子甚至一幢樓大小的大型機而言的,事實上小型機的體積一般比冰箱還大,而且性能相對大型機也是慘不忍睹。

但優點是價格便宜,而且安裝起來也相對方便,所以在民用與商用市場上很火爆,美國早期的程序員基本都有使用PDP的經歷,而世界上早期的遊戲也是出現在該機器上。

俗話說,有志者,事竟成,三巨頭用了幾年都沒能搞定的事情,卻被肯·湯普森一個人在這台廢舊電腦上花了一個月就搞定了。不到一個月,肯·湯普森便對MULTICS系統進行了精簡,用彙編語言(上章提到過,還有印象嗎?)寫出了一個更為簡潔的版本。

然而當他向同事展示他的成果時,他的同事卻對這個精簡版的MULTICS極為不認可,甚至給其起了個綽號叫Unics,大致的意思就是超簡陋版MULTICS。不過肯·湯普森也不生氣,乾脆就把他的新系統命名為Unics。

而兩年後,該系統在經過了重構與更精簡後,被重新根據其更精簡的特性,命名為:Unix。

註:Unix的讀音與Unics相同,但少一個字母。後來,肯·湯普森對這種將事物極簡至原子化的哲學理念總結為:KISS原則,而KISS原則也是Unix系統一貫的核心設計哲學。

關於更多KISS原則內容,請大家自行上搜索網站查閱,看不懂或半懂不懂沒關係,先記下,代碼寫多了後自然會理解。

一道驚雷劃破天空,一個時代就此誕生,近50年後的今天,世界上有95%的計算機正運行著 Unix與它的衍生系統,FreeBSD、OpenBSD、MacOS、iOS、Linux、Minix、Android,幾乎除了Windows外所有的操作系統皆為Unix衍生系統,不知當年嘲笑肯·湯普森的那些同事如果活至今日,是否羞愧欲死呢?

Unix大家族族譜,由於該圖是2008年畫的,遺漏了Android與iOS等

隨著肯·湯普森的不懈努力,貝爾實驗室的科研人員在嘲笑完Unics後,卻逐漸意識到了這個『簡陋』的系統其實相當的好用,於是在實驗室內部迅速得到了推廣。然而由於當時實驗室中有大量不同類型的計算機存在,而不同的計算機,其指令是不同的,比如:

在 PDP-7上可能加指令為數值3,可能有兩個操作數,而 System/360上加指令對應數值則可能是7,可能有三個操作數,甚至另一台XXX計算機上可能都沒有加指令,而是用別的方式去執行加運算

而Unics系統又是由機器指令直接翻譯過來彙編語言寫的,不同的計算機由於機器指令不同,彙編指令顯然也是不同的。所以,為了讓Unix系統能在實驗室內不同的計算機上運行,肯·湯普森必須要針對不同的計算機指令集,反覆去用不同的指令集重寫Unics系統的源碼,而這樣做顯然既耗時間,又很無聊,還顯得特蠢。

面對這種情況,在實驗室另一名科研人員,丹尼斯·李奇Dennis Ritchie的幫助下,他們決定使用當時新興的一種稱為高級語言的概念,去重寫Unix系統,並希望藉此能減少重複開發的工作量,使Unics更易於推廣。

那麼,究竟什麼是高級語言呢?有多高級呢?

四、高級語言與編程語言的發展

在上一章中,鄙人向大家提到了,最早的程序是直接由計算機指令編寫而成的,本質上也就是一串二進位數字而已,舉個例子(這裡指令都是瞎掰的,不過沒關係):

第一行:0100 0100 0010第二行:0100 0101 0000第三行:0110 0100 0101說明,每行格式為:指令類型_操作數1_操作數2

然而這樣一串二進位數字看著幾乎難以直接理解,能直接看懂的都有上超強大腦節目的潛力。所以,編程人員在閱讀這樣的程序時,必須要不停的比對程序數字與指令表去一條一條的理解程序的意思,比如:

對上述程序進行逐行查表翻譯得知,

第一行:0100 0100 0010注釋:操作類型:0100,代表移動右邊數值到左邊寄存器指令,操作數1的0100代表寄存器A,操作數2的0010代表十進位數值2,那本行代碼意為將寄存器A的數值改為2。第二行:0100 0101 0101注釋:操作類型:0100,代表移動右邊數值到左邊寄存器指令,操作數1的0101代表寄存器B,操作數2的0101代表十進位數值5,那本行代碼意為將寄存器B的數值改為5。第三行:0110 0100 0101注釋:操作類型:0110,代表將左右兩個寄存器相加指令,操作數1的0100為寄存器A,操作數2的0101為寄存器B,那麼本行代碼意為將寄存器B的值加到寄存器A上

我們可以看到,即使是簡單的三行代碼,已經非常累人,如果程序有幾萬行這樣的指令,要看懂則幾乎是不可能的事情。所以,面對這種情況,就有人想出了助記符這個概念。

所謂助記符從字面意思上就可以理解為『幫助人類記憶的字元』,其本質上其實就是用一些人類能一眼看明白的字元串去替換指令中的一些固定的內容。

舉個例子,比如用上助記符,用字元替換了部分內容後,上述程序就變為了:

第一行:MOV REG_A 0010第二行:MOV REG_B 0101第三行:ADD REG_A REG_B其中,MOV為英文Move移動的縮寫,替換了第一列操作類型:0100,代表轉移指令,REG_A 或 REG_B 中 REG 即英文 Register 寄存器的縮寫,REG_A替換了第一行操作數1:0100,代表寄存器AREG_B則替換了第二行操作數2:0101,代表寄存器BADD則為英文中加的意思,替換了第三行的操作類型:0110,代表加指令。

有了助記符後,上述程序顯然已經能讓人一眼就看懂,用此語言書寫的代碼從而再也不需要逐條查表,大大提高了編碼與閱讀的效率,而這種用了助記符的語言就稱為彙編語言。

彙編語言出現不久後,更有人乾脆開發了一個小程序,能將以助記符形式輸入到計算機的彙編程序,自動轉換為計算機能執行的機器指令,而這種小程序就叫做編譯器

編譯器:將人類能看懂的編程語言轉換成計算機能執行的機器指令的程序

編譯:將人類能看懂的編程語言轉換成計算機指令的操作

反編譯器:將機器指令轉換回人類能看懂的編程語言的程序


有了編譯器後,人們又發現,即使彙編語言已經足夠的易懂,但依然遠遠不夠,因為彙編語言的編碼邏輯其實本質上依然沒改變,是以計算機操作邏輯去編寫的,而並非人類的思維習慣,什麼意思呢?

舉個例子,比如上述例子中,我們做了個2+5的運算,如果按人類的思維習慣,這個程序應當寫作:

2 + 5 = ?

而按計算機邏輯卻變成了:

MOV REG_A 0010 ;2加到寄存器AMOV REG_B 0101 ;5加到寄存器BADD REG_A REG_B ;把寄存器B的值加到寄存器A上,寄存器A中的即為結果

顯然,對人類而言,按人類思維習慣的數學公式遠比按計算機執行邏輯的彙編語言要好懂得多,而且精簡的多。

基於這個原因,在人們發明了編譯器後,就想了,既然已經能用編譯器將機器語言編程轉換為彙編語言編程了。

何不更進一步,乾脆發明一種基於人類更好理解的語言的編程語言,然後由功能更強大的編譯器程序去直接轉換呢?讓編譯器去處理更複雜的人類邏輯到計算機邏輯的轉換。

所以科研人員在提出了這個概念後,便針對語言是否易於人類理解,將編程語言劃分為了:

低級語言:按機器操作邏輯與指令編寫,人類不好理解,一般就是指彙編語言與機器語言,編譯器一般可以做得極簡單,幾千行代碼就能寫一個

高級語言:易於人類理解,按人類思維習慣編碼,與機器操縱邏輯無關,編譯器更複雜更強大,也更難開發,有門課叫編譯原理,專門講這個,數學不好的就別看了

在高級語言的概念推出後,很多科研人員對其產生了濃厚的興趣,短短几年內,便出現了大量的高級語言編譯器,比如:

FORTRAN語言:第一種高級語言,至今仍在科研領域與金融行業被大量使用,因為用其寫數學運算程序很方便,性能也很高。

ALGOL語言:劍橋大學開發的一種高級語言,現已不多見

CPL語言:劍橋大學在ALGOL語言上開發的一種新高級語言,現已不多見

BCPL語言:劍橋大學在CPL語言上開發的一種新高級語言,現已不多見

PASCAL語言:瑞士人發明的一種高級語言,其變種如今依然被大量使用,如Delphi平台所使用的 Objective-Pascal,微軟公司和蘋果公司與該語言關係很深

BASIC語言:一種面向初學者的功能有限的高級語言,鄙人學得第一種語言,由於其開發簡便,邏輯簡單,目前微軟的Visual Basic平台依然在很多領域使用

Lisp語言:60年代初就誕生的一種非常獨特的高級語言,函數式編程語言(如Python)的鼻祖,雖然與本Java課程無關,但由於其獨特的地位,一起列上

在科研人員對於高級語言編譯器的研發過程中,人們又逐漸發現了高級語言擁有第二個特性,也是我們的肯·湯普森與丹尼斯·李奇最感興趣的一個特性,可移植性

由於高級語言相對於低級語言更接近人類的思維邏輯,而與具體的計算機執行邏輯無關,所以用其開發的代碼往往能通過針對不同機器開發的編譯器的編譯,輕鬆兼容不同計算機,而這恰恰正好解決了肯·湯普森所頭疼的問題。

於是,在1970年,經過幾年的努力,肯·湯普森在BCPL高級語言的設計基礎上,開發了一種名為B語言的新高級語言,例子如下(具體含義大家先不用管):

/* The following function will print a non-negative number, n, tothe base b, where 2<=b<=10, This routine uses the fact thatin the ANSCII character set, the digits 0 to 9 have sequentialcode values. */printn(n,b) {extrn putchar;auto a;if(a=n/b) /* assignment, not test for equality */printn(a, b); /* recursive */putchar(n%b + 0);}

這種語言相對於BCPL語言更為簡潔,寫起來也更輕鬆,其編碼邏輯也更接近人類思維習慣。所以在發明B語言後,肯·湯普森便嘗試使用B語言重寫Unics系統,然而:

浪費了大把的時間,卻發現這就是個坑!

完成後他卻無奈得發現,使用B語言開發編譯的Unics系統雖然的確解決了機器兼容性問題,但其執行性能卻差了彙編版本一大截,遠遠達不到要求。

所幸,他有貴人相助,在丹尼斯·李奇了解了B語言的設計後,針對B語言編寫的程序執行性能不佳的情況,又與肯·湯普森一同做了一番改進,優化了其中大量繁瑣和不合理的設計,去除了會影響編譯後生成的機器代碼執行性能的錯誤語法。

最終,在1972年,他們完成了夠自己享譽一生的傑作,一種能兼顧可移植性、執行性能、功能強勁又不失美觀的全新高級語言就此誕生,C語言。並用該語言重寫了Unics系統,然後重新命名了該系統,稱為Unix 1.0。

如今,已經45年過去了,C語言依然寶刀未老,藉助其與Unix系統牢不可破的聯盟,常年名列世界使用人數最多的計算機語言排行榜上第二或第三位(有些變化,但基本前三),離開了Unix系統與C語言,我們的計算機世界將不復存在,因為Unix系統與C語言正是所有計算機軟體的根基所在,幾乎所有的計算機標準幾乎都是以Unix系統與C語言程序的形式所定義。

所以在本章最後,鄙人便以一張照片紀念那輝煌的一刻:

肯·湯普森與丹尼斯·李奇在PDP-11前工作

五、結語

本章節鄙人向大家簡單闡述了操作系統與編程語言的起源,以及每個發展的內在原因,下個章節開始,我們將為大家引入Java語言,並正式開始Java的學習。

六、作業與問題

本章無作業,暫時無問題

七、章節目錄鏈接

零基礎編程入門系列,前言及目錄

推薦閱讀:

從NASA到Intel,編程貓學員在矽谷收穫了哪些技能?
編程中國
編譯原理學習
關於學習四品八德有哪些名人名言可以引用?
Tumblr:我們是如何從 PHP 5 升級到 PHP 7 的

TAG:編程 | 編程語言 | 操作系統 |