Note1:APUE引言
一、UNIX/Linux前世今生
UNIX來源
20世紀60年代是大型、復雜操作系統盛行的年代,比如IBM的OS/360和Honeywell的Multics系統。OS/360是歷史上最成功的軟件項目之一,而 Multics雖然持續存在了多年,卻從來沒有被廣泛應用過。貝爾實驗室曾經是Multics項目的最初參與者,但是因為考慮到該項目的復雜性和缺乏進展而于1969年退出。鑒于Mutics項目不愉快的經歷, Bell實驗室的?Ken Thompson?開始利用一臺閑置的 PDP-7計算機開發了一種多用戶,多任務操作系統。很快,Dennis Richie?加入了這個項目,在他們共同努力下誕生了最早的UNIX。Richie?受一個更早的項目——MULTICS的啟發,將此操作系統命名為 Unix。早期UNIX是用匯編語言編寫的,但其第三個版本用一種嶄新的編程語言C重新設計了。C是?Richie?設計出來并用于編寫操作系統的程序語言。通過這次重新編 寫,Unix得以移植到更為強大的 DEC PDP-11/45與11/70計算機上運行。后來發生的一切,正如他們所說,已經成為歷史。 Unix從實驗室走出來并成為了操作系統的主流,現在幾乎每個主要的計算機廠商都有其自有版本的Unix。
POSIX來源
20世紀80年代中期,隨著UNIX成長后來占領了市場,公司多了,懂得人也多了,就分家了。Unix廠商試圖通過加入新的、往往不兼容的特性來使它們的程序與眾不同,麻煩也就隨之而來了。為了阻止這種趨勢,IEEE(電氣和電子工程師協會)開始努力標準化Unix的開發,后來由 Richard Stallman?命名為“POSIX(Portable Operating System Interface of UNIX)”。結果就得到 了一系列的標準,稱作Posix標準。這套標準涵蓋了很多方面,比如Unix系統調用的C語言接口、shell程序和工具、線程及網絡編程。“UNIX”這個名字由于法律關系,誰也不能說自己的操作系統是“UNIX”而只能說是“UNIX兼容”系統了。所以現 在“UNIX”系統嚴格意義上說是不存在的,存在的只是一個遙遠的傳說。那么現在那些Solaris,AIX,IRIS,macOS都是什么呢?那些都是各公司在他們硬件平提上作的商業UNIX,這些系統都遵循POSIX標準。
GNU來源
GNU就是GNU's Not Unix的縮寫, GNU 的創始人Stallman認為UNIX雖然不是最好的操作系統,但是至少不會太差,而他自信有能力把UNIX 不足的地方加以改進,使它成為一個優良的操作系統,就是名為GNU的一個同UNIX兼容的操作系統,并且開發這 個系統的目的就是為了讓所有計算機用戶都可以自由地獲得這個系統。任何人都可以免費地獲得這個系統的源代碼,并且可以相互自由拷貝GNU 是由自由軟件基金會 (Free Software Foundation,FSF)的董事長Richard M. Stallman (RMS)于1984年發起的,如今已經有十幾年的歷史了。
GNU 開始的策略就是先開發UNIX已經有的程序(因為計劃中GNU將會是一個與UNIX兼容的操作系統,而UNIX下的標準使用界面已經非常完善了,所以先依照這個標準開發應用程序,將來GNU自己的系統核心一出來,就立即可以使用所有先前開發的 GNU 應用程序),因此會先有emacs,GCC等工具軟件開發出來。其中GCC更是GNU計劃自立更生的一個重要步驟(不需要依 靠商業軟件來產生/編譯整個GNU系統),如今這套程序開發工具已經很成熟了。下一步要做的就是開發GNU的核心--Hurd 了,只要Hurd一開發出來,GNU 就是一套能夠自我開機,真正自給自足,完整的自由操作系統。
Hurd是基于Mach這個微內核(micro kernel)上的操作系統核心。以后會使用尤他大學的Mach4(一個更為方便和快速的微內核),由于Hurd基于Mach,所以只要Mach移植到什么機器上,Hurd也立刻就是這種硬件平臺的操作系統,就這一點而言,它是一種很前衛的操作系統。但是,GNU的操作系統核心Hurd一直處于實驗階段,沒有任何可用性,實質上也沒能開發出完整的GNU操作系統,但是GNU奠定了Linux用戶基礎和開發環境。自由軟件基金會目前有一套以Linux為核心的GNU系統計 劃。這個計劃就是自由軟件基金會支持的 Debian Linux。 Debian Linux 是GNU軟件與公共軟件(Public Domain Software) 最徹底的結合,它是一套完全由GNU和公共軟件配置起來的,而且具有商業操作系統水平的操作系統。
Linux來源
Linux起源于一個學生的簡單需求。Linus Torvalds,Linux的作者與主要維護者,在其上大學時所買得起的唯一軟件是Minix。Minix是他的老師為講解操作系統原理這門課寫一個類似Unix操作系統,它被廣泛用來輔助教學的簡單操作系統。Linus 對Minix 不是很滿意,于是決定自己編寫軟件。他以學生時代熟悉的Unix作為原型, 在一臺Intel 386 PC上開始了他的工作。他的進展很 快,受工作成績的鼓舞,他將這項成果通過互連網與其他同學共享,主要用于學術領域。有人看到了這個軟件并開始分發。每當 出現新問題時,有人會立刻找到解決辦法并加入其中,很快的, Linux成為了一個操作系統。值得注意的是Linux并沒有包括 Unix源碼。它是按照公開的POSIX標準重新編寫的。Linux大量使用了由麻省劍橋免費軟件基金的GNU軟件,同時Linux自身也 是用它們構造而成。
?
二、站在十萬八千里的高度
在linux/unix的世界里,“萬般皆下品,一切皆文件!”這句話是linux/unix的哲學核心思想。從1991.10.5年?Linus Torvalds 在自己學校FTP站點上正式向外發布第一個穩定的Linux內核工作版本到今天,正是由于這種“簡單粗暴而又妖嬈”的設計,才使得今天發生翻天覆地變化,我們在Linux/UNIX下編程時依然使用同一套API(Application Program Interface)。12年前的我剛開始接觸Linux編程時學習的是大神 Richard Stevens 所著的《UNIX高級環境編程,業界簡稱APUE》和《UNIX網絡編程,業界簡稱UNP》,12年后的今天,在帶大家學習Linux下編程時依然倍加推崇這兩本書。其中《APUE》是所有Linux下所有 程,序開發者的入門必備良藥,《UNP》是所有從事Linux網絡編程人員的必讀書籍。
從現在開始,我們就開始帶領大家走進Linux下的編程世界,而這個窗戶就是《APUE》。在《APUE》這本書基本上覆蓋了 Linux下所有編程相關的知識點,結合這么多年的嵌入式Linux開發經驗,我把這本書需要重點掌握的內容大致分為以下幾大塊:
- 文件I/O: open()、read()、write()、ioctl()、close()
- 多進程編程: fork()、getpid()、getppid()、exec*()、system()、popen()
- 多線程編程: pthread_create()、pthread_join()、pthread_exit()
- 網絡編程: socket()、bind()、connect()、accept()、read()/recv()、write()/send()、close()
- 多路復用: select()、poll()、epoll()
- 進程間通信(IPC): 管道(pipe)、命名管道(named pipe/FIFO)、消息隊列(Message Queue)、信號量(Semophore )、信 號(signal)、共享內存(Shared Memory)、網絡通信(sockt和named socket)
?
三、系統調用與庫函數
Linux下對文件操作有兩種方式:系統調用(system call)和庫函數調用(Library functions)。在《APUE》這本書中講的絕大部分函數都是系統調用,而非庫函數。
系統調用
系統調用,我們可以理解是操作系統為用戶提供的一系列操作的接口(API),這些接口提供了對系統硬件設備功能的操作。可 以舉個例子,我們最熟悉的 hello world 程序會在屏幕上打印出信息,程序中調用了printf() 函數,而庫函數 printf 是將需要打印的信息輸出到屏幕這個硬件設備上。我們知道,對于所有硬件設備的操作都需要驅動程序,而驅動程序是由操作系統內核實現的。這也就意味著我們的printf()函數最終需要調用Linux內核的相關函數來操作屏幕這個設備,而這些函數就是系統調用。事實上,printf()庫函數的實現里最終會調用系統調用 write() 。
庫函數
庫函數可以理解為是對系統調用的一層封裝。系統調用作為內核提供給用戶程序的接口,它的執行效率是比較高效而精簡的, 但有時我們需要對獲取的信息進行更復雜的處理,或更人性化的需要,我們把這些處理過程封裝成一個函數再提供給程序員,更方便于程序猿編碼。譬如在接下來的學習過程中,我們會學習read(int fd, char *buf, int size)這個系統調用,這個函數是從某個文件(由fd)標志中,讀取最多不超過size個字節的數據并存放到buf中去,在這個系統調用中我們只能指定讀N個字節的數據,而對于想一次讀取一行這樣的需求則可以調用庫函數fgets()來實現,這在《C Primer Plus》的文件/IO中講到,當然在《C Primer Plus》里提到的所有函數都是庫函數。
系統調用和庫函數
庫函數有可能包含有一個系統調用,有可能有好幾個系統調用,對于不需要涉及內核的功能的庫函數也不需要調用系統調用, 比如strcpy()、strstr()、strlen()這些函數等。 對于一個功能,我們有時既可以使用系統調用來實現,也可以使用庫函數來實現,也沒有強制的規定,根據大家的實際需求來選擇。譬如對于文件的操作,我們可以使用open()、read()、write()、close()這些系統 調用實現,當然我們也可以使用fopen()、fread()、fwrite()、fgets()、fclose()這些庫函數來實現,只有對比了解他們各自的特性我們針對不同的情況作出一個最優的選擇。
總結
以上是生活随笔為你收集整理的Note1:APUE引言的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么修改CAD图纸中部分图块的颜色?
- 下一篇: 高速数据采集卡的机理分析