編譯器和作業系統

來源:互聯網
上載者:User

 

和很多程式員一樣,編譯器到目前為止對我還存在一些讓我迷惑的地方。比如編譯器與作業系統的關係,編譯器與CPU的關係,動態連結器從哪尋找共用庫等。讓人困惑的原因有幾,第一是編譯器的功能角色特殊,編譯器是產生程式的程式;第二是編譯過程變得越來越複雜[注],一支編譯器支援多種程式語言、支援共用庫、編譯最佳化,編譯與連結可分開等;第三,作業系統的介入。本文試著從第三點——作業系統介入編譯過程後對編譯器的影響,看看作業系統與編譯器有什麼關係。

  註:編譯過程變複雜源於電腦應用變複雜。例如應用程式項目越來越龐大,功能越來越多;為了管理大項目,拆分來源程式檔案為多個;為了提高程式的效能,目標程式檔案的連結期被延遲到運行前;為了程式的靈活安裝和升級,引入各種指令碼工具,如make,configure(shell)。

  編譯器

  我們看看編譯器的一種傳統定義:

  編譯器是一支將抽象度較高的程式設計語言程式(也稱來源程式)【轉化】成抽象度較低的程式設計語言程式(也稱目標程式)的【程式】[注]。抽象度的兩端分別是機器語義和人理解語義。【處理器體系】和【程式設計語言】是一支編譯器的根本屬性。

  註:以下僅使用【程式】一語,“器”是一種形象的比喻,不夠嚴謹;而軟體(software)是產品性的程式,最好只用在商業語境中。

  以上對編譯器的定義描述在【現代意義下】對全面認識編譯器是不夠的,因為它沒有涉及作業系統,沒有涉及現代的複雜的程式構建過程。有一定開發經驗的程式員都知道,程式的“編譯過程”包括編譯、連結(靜態連結與動態連結)、調試,還可能包括組態配置和安裝兩步。“編譯”一詞已經不能很好描述這個過程。整個過程可稱為【程式構建】,而編譯只是第一步,在這一點上,編譯器在傳統意義上與現代意義上產生了不同。由於本文試圖討論編譯器與作業系統的關係,為了避免產生歧義,本文的【編譯器】包括編譯和靜態連結兩個部分,動態連結部分有點特殊,後面會提到它的角色。

  下面我們給出有關【作業系統與編譯器關係】的三個問題,並試圖回答它們:

·第一,編譯器與作業系統的關係是什嗎?

·第二,編譯器對作業系統有依賴嗎?

·第三,編譯器與CPU的關係又是什嗎?

·第四,作業系統對C標準庫與C編譯器的關係有什麼影響?

  為了更好的進行下一步討論,我先給出現代編譯器比較完整的定義,並由定義引出問題:

  現代編譯器是一支將某抽象度較高的程式設計語言程式【轉化】為運行在【某軟硬體系下】的抽象度較低的程式設計語言程式的【程式】。所謂硬體體系是指處理器體系,軟體體系指作業系統體系。

  要回答前三個問題,我們得釐清現代編譯器定義中的【屬概念】——程式,並對作業系統有更深一層認識。

  程式

  程式的分類是多種多樣的,比如常見的兩分法是【系統程式】和【應用程式】。這是一種粗粒度的按【計算任務】不同的分法。我們看程式的定義:

  程式(program)是完成特定【計算任務】的【指令】序列,指令由相應的【圖靈機】讀取並操作。

  由以上對程式的定義可知,還可根據——程式【指令的性質】和讀取程式的【圖靈機】性質——兩個標準再進一步對程式分類。比如,按指令序列是否連續可以分為獨立程式和共用程式(使用了共用庫);按指令的抽象度可分為進階語言程式和低級語言程式。按【圖靈機】的體系可分為X86程式和ARM程式,16位程式和32位程式等。

進階語言程式是不是【程式】?如果是,它的【圖靈機】是什嗎?

我們一般理解下的【程式】是指二進位的可執行檔,那麼進階語言的來源程式是不是程式?從指令序列的定義看,【進階語言的來源程式】是程式,因為【進階語言的來源程式】與【二進位的可執行檔】一樣,也是指令序列,只不過【進階語言的來源程式】的【圖靈機】不是CPU,也不是編譯器或解譯器,而是程式員。【進階語言的來源程式】的功能更多體現在程式員間的相互學習和交流。

  除了以上基本分類外,現代的程式還會受為其提供虛擬運行環境的作業系統影響,可以根據作業系統的體系屬性對程式再分類,例如win32程式,linux程式。

  作業系統

  作業系統是什麼類程式?

  作業系統是一類比較獨立的系統程式,作業系統有支援各種【圖靈機】的體系類型,比如16位DOS,32位Windows,X86的BSD,ARM的 Linux等。而系統程式一般是指一支為應用程式直接提供半成品(為應用程式提供執行的虛擬環境)和協調多個應用程式並行啟動並執行程式。所謂半成品是指,系統程式的一部分(指令序列)也是應用程式的一部分(指令序列),但這部分程式不專屬任何應用程式,它是共用的。例如各種新硬體的驅動程式、C標準庫函數、POSIX庫函數等。而作一個協調程式,作業系統表現出與一般應用程式的程式性,如獨立調度的線程,只是它們運行在權力更高的狀態下。協調程式如線程發送器。

  非作業系統程式與作業系統的關係

  這裡的作業系統泛指像Linux這樣的現代32位作業系統,而【非作業系統程式】運行在作業系統之上,對作業系統存在可能的依賴的程式。

  其實只要是運行在某作業系統之上的程式都會烙上該作業系統的印,對作業系統有依賴,包括編譯器。不過這些程式對作業系統的依賴程度和依賴的內容確實有很多區別。例如一支最簡單的【Hello world程式】都會對【作業系統的C庫】產生依賴,如果去掉【Hello world程式】的輸入輸出功能,只作加減或邏輯運算,【Hello world程式】依然會對作業系統有少量依賴,因為【Hello world程式】由運行在該【作業系統上的編譯器】編譯的,有特定的目標檔案格式,並由該【作業系統的載入程式】載入記憶體運行[注]。這種只【在形式上】對OS存在依賴的“無用”程式可謂是最獨立於OS的程式。在此基礎之上,其它程式都對OS有不同程度的依賴,依賴表現在對OS內的各種程式庫的依賴,比如C標準庫,POSIX系統庫,線程庫、網路程式庫和其它基於這些基礎庫的第三方應用程式碼程式庫。

  註:由此可見編譯器與引導程式、SHELL程式一樣,是現代作業系統的基本部分。

  問題初步解決

  編譯器與作業系統的關係

  有了以上的對程式以及作業系統本質的一定瞭解後,我們知道編譯器與作業系統有一定親緣性。但這種親緣性的一些表現會讓人迷惑。例如Linux發行版可以不安裝有編譯器的,只有開發工作站才需要編譯器。而所有Linux發行版的應用程式都可能使用了共用庫,需要動態連結這些系統共用庫。由此可見,應該分開【開發期】與【運行期】來看待編譯器與作業系統的關係。在開發期,編譯器運行作業系統之上,屬於【非作業系統程式】,對作業系統有依賴;在運行期,編譯器的子部分——動態連結程式和載入程式屬於作業系統有機部分。

  由以可得編譯器與作業系統的關係有:

·第一,編譯器的編譯部分和靜態連結部分是運行在作業系統上的系統程式;

·第二,編譯器的動態連結部分與作業系統的親緣性更強,所以完全可把動態連結部分獨立出來[FIXME:動態連結程式與作業系統具體關係未知];

·第三,編譯器的編譯輸出格式是作業系統相關的。

  由此可見,編譯器是作業系統相關的,編譯器也是作業系統的功能很重要組成部分,但編譯器沒有被整合入作業系統核心內,所以編譯器不算是作業系統的有機組成部分。

  編譯器對作業系統的依賴

  由上面可得,編譯器是運行作業系統之上【非作業系統程式】,對作業系統有依賴。編譯器是一支【計算集中】更大的程式,它相對於應用程式對OS依賴會少一些,依賴有:

·形式依賴(由另一支同軟硬體系的編譯器[行話本地編譯器],編譯得到或不同軟硬體系的編譯器[行話交叉編譯器],交叉編譯得到)

·C庫依賴,讀取進階語言源碼程式檔案,寫入低級語言的目標檔案

  編譯器與CPU的關係

  這個問題在編譯器的定義裡已經有答案了,一支編譯器只編譯產生一種機器碼。我們說編譯器的【作業系統相關性】是後天進化得到的,而編譯器的【處理器相關性】是天生的。

  作業系統對C標準庫與C編譯器的關係的影響

  作業系統對C庫沒有什麼影響,C庫是一種通用程式碼程式庫。是給使用者編程提供的介面,程式員只需要和這些介面打交道就可以了,而不需要知道具體怎麼實現的。c庫中的有些功能是c庫代碼本身實現的,也有一些是利用作業系統實現的。 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.