操作系統那些事

現代操作系統的實現是一個高度抽象的、複雜的、偉大的工程。本文主要是簡單介紹操作系統裏面的最重要的三個抽象概念:進程,虛擬地址空間,文件,以及他們各自涉及到的相關要點。

 

進程

進程是對cpu的抽象,cpu是執行一條條的指令,進程被抽象爲程序的執行流。

 

跟進程相似的一個概念是線程,其中線程可以再分爲2類,一類是用戶級線程,也就是posix線程(c語言裏面的pthread類函數);還有一類是內核級線程(輕量級進程)。前者只是在用戶空間運行,不會被進程調度器所管理,所以在多SMP的環境下,它體現不出良好的性能。後者則能夠被內核中的進程調度器所管理,但是由於需要上下文的切換,即從用戶空間和內核之間切換,這需要一定的開銷,但是比純進程的上下文切換開銷要小。

 

所以可以這麼總結,上下文切換開銷:進程>輕量級進程>線程

                  SMP環境下的優勢:進程>輕量級進程>線程

 

再談談進程和線程(posix線程,輕量級進程介於2者之間,不多說了)的聯繫和區別。

聯繫:

首先,不管是進程還是線程,它們都是對cpu的抽象,都是程序執行流。其次,線程必須依賴於其所在的進程才能存在,沒有進程,何談線程。默認情況下,可以認爲一個進程裏面只有一個線程(主線程),可以通過調用c語言函數pthread_create()產生一個線程,相對於初始的主線程,這個線程叫做對等線程。最後2者都有三種狀態,運行、就緒、等待。就緒狀態是等待cpu到達,等待狀態是進程阻塞在某種狀態,比如IO操作的完成

區別:

每個進程有自己的地址空間(即下文將會談到的虛擬地址空間),一般情況,虛擬地址空間的範圍(32位機器)是04G,記住,這是虛擬的空間,是操作系統對內存的抽象,實際上它是通過頁表映射到物理內存的,比較一般的進程佔用的物理內存大約就是20M左右。線程是依賴於其所在進程的,也就是各個線程共享進程的地址空間,能夠看到進程當中的各個變量,文件描述符等。當然線程也有自己獨有的地址空間,即線程棧。

由於進程擁有獨立的地址空間,所以進程之間通信變得相對麻煩,一般可以通過信號,隊列,共享內存,socket進行通信。線程之間也可以通過這些機制進行通信,但是由於各個線程共享所在進程的地址空間,所以通信變得比較容易。

 

最後簡單說說進程之間的關係。系統啓動的時候有個進程id1init進程,這個進程是整個系統中最主要的,很多進程都是由它fork出來的。當父進程死掉時,一般是由init進程對其子進程進行回收的,避免子進程變爲殭屍進程(無用進程,但是佔用資源)。很多時候父進程需要顯式地等待子進程死亡,然後爲他收屍。另外,一類的進程形成進程組,進程組有個進程組id

 

虛擬地址空間

虛擬地址空間是對存儲器的抽象,對於程序員或者進程來說,進程的尋址範圍(32位機器)是04G。這4G的空間被分爲棧、堆、BSS(未初始化的數據段)、已初始化的數據段、程序正文段。當程序從磁盤載入時,程序正文段、已初始化的數據段被寫入相應的數據,BSS中的變量被初始化爲0。堆、棧在最初的時候是空的。

虛擬地址空間只是操作系統提供給進程的一個友好的存儲器模型,實際上,進程的一切行爲都是發生在物理存儲器上的。那麼就需要一種機制將虛擬地址空間映射到物理內存,這就是頁表。將虛擬地址空間和物理存儲器劃分爲多個頁面(二者之間的頁面大小一般是相同的,典型地爲4k),這樣每個虛擬頁就可以根據頁表表項映射到對應的物理頁。

 

程序被執行時,cpu會將pc寄存器中的地址送到內存總線,比如:mov ax 0x123456780x12345678這個地址是虛擬地址。很顯然,只靠頁表是不能夠找到對應的物理地址的,因爲頁表粒度太粗了,所以引入了一個MMU(內存管理單元),它根據頁號和頁面偏移將物理地址計算出來。

 

頁表是存放在內核中,而且是每個進程都有對應的頁表。這樣的話,一方面是每次物理地址計算,都多了一次內存訪問,內存訪問速度相對於cpu來說是小巫見大巫。又根據程序一般具有局部性,就是說每個程序反覆用到的頁面只有那麼幾個。這種情況在計算機領域是很常見的,沒錯,就是使用更nb的設備把它緩存起來,這就是TLB,它的作用是根據虛擬頁號快速地找到相應的物理頁號。然後再使用MMU計算出物理地址。另一方面的問題是,4G的虛擬地址空間,4k的頁面大小需要100萬個頁表表項。即使每個表項1B(其實肯定不止啦),都要1M的空間。這個問題可以通過多級頁表來解決。

 

另外,如果某個虛擬地址不能在當前的頁表中找到相應的物理頁號,這種情況叫做缺頁中斷。這會cpu陷入內核,使用某種算法將某個物理頁面淘汰出去。淘汰是這樣進行的:如果這個頁面被進程修改過了,那麼將其寫入磁盤,否則只是簡單地丟棄。然後將相應的頁面從磁盤中載入到物理頁面中,接着修改頁表表項

 

虛擬內存的概念是經過高度抽象化的,早期的操作系統是沒有虛擬內存的概念,所以將cpu送出的地址(物理地址)直接送往存儲器總線,這導致多道程序設計相當麻煩,歷史上曾經使用基址寄存器和界限寄存器進行解決,但效果不好。另外針對內存超載,曾經使用過swapping技術進行解決,即將進程換出到磁盤。也使用過覆蓋的方式,將程序劃分爲一個個段,相當之麻煩。自從有了虛擬內存,我們生活在幸福的時代。但是不應該忘記歷史,一是不重複歷史,二是某些技術可能在嵌入式等低端設備上變得相當可行。

 

文件

文件是對磁盤的抽象。磁盤(專業一點叫磁盤驅動器)是由一個個盤片組成的,柱面,磁道,扇區的概念不說了,現代磁盤的構造相對比較複雜。但是基本上還是由盤片,柱面,扇區這3個元素來決定的尋址的。盤面的上方有磁盤臂在移動,用於磁盤尋道。SATA接口的磁盤讀取數據的速度大約100MB/s,但這僅僅是數據傳輸速度,還要考慮尋道和等待時間,這2個是耗時的操作。

 

磁盤中有個叫MBR的很小的區域,它是用來存放分區信息和引導程序的,因爲MBR太小了,所以分區的數量是有限制的,linux系統中最多4個主分區。MBR會確定活動分區,讀入分區的第一個塊——引導塊,引導塊中的程序將會裝入該分區中的操作系統。引導塊之後是超級塊,空閒空間,i節點,根目錄,文件和目錄。每一分區對應一個文件系統,所以i節點的概念是對於一個分區來說的,也就是說一個系統中可以由重複的i節點。所有的文件系統之上又有一個虛擬文件系統,對上層提高統一的接口。

 

先解釋2個重要概念:

i節點是一個數據結構,一般情況下,一個i節點對應一個文件,它記錄了文件的信息和文件的磁盤地址,不包括文件名。

目錄項,其實linux中,目錄也是被當做文件的,那麼目錄中的內容是什麼呢?就是目錄項,目錄項是由文件名和i節點組成的。硬連結是通過增加目錄項來實現的,刪除一個連結文件的時候,就把對應的目錄項給刪了,但不會刪除i節點,直到沒有目錄項指向i節點時,纔會刪除i節點。

 

剛剛說過,文件是對磁盤的抽象,所以當我們創建一個文件時,然後往其中寫入一些信息,然後保存,映射到磁盤上就是一些磁盤扇區被寫入相應的信息(包括i節點信息,目錄項信息,數據信息),這中間涉及到比較多的細節。接下來根據本人的理解,簡單介紹。

 

當我們在進程中打開一個文件的時候,是怎樣定位到相應的磁盤的磁道上?一般情況下,文件系統的根目錄i節點都是隨系統啓動而保存在內存中的。當要查找/usr/jonda/my.txt時,系統可以容易地知道根目錄/i節點找到對應的磁盤地址,然後找到目錄項usr,然後找到usri節點,然後找到usr的磁盤塊,然後找到usr的目錄項jonda,然後找到jondai節點,然後找到jonda的磁盤塊,然後找到jonda的目錄項my.txt,然後找到my.txti節點,然後找到my.txt的數據。

 

文件的內核數據結構保存在進程表項中,其中包括fd,文件表,i節點表,fd指向文件表表項,文件表表項有一個指針指向i節點表表項。文件表中最主要的是文件的偏移量(fork進程的時候,父子進程共享文件表)。i節點裏的信息上面已經說過(磁盤裏的i節點只是記錄信息,只有放到內存中,纔有數據結構可言,才能被進程直接訪問)。

 

打開之後便是讀寫文件,現在的計算機都是使用DMA技術進行文件讀寫的。DMA裝置是一個芯片,它代替了以前使用cpu直接進行磁盤的讀寫文件。下面講述一下文件的讀取操作,它是cpuDMA控制器(DMA控制器有字節計數寄存器,內存地址寄存器,控制寄存器),磁盤控制器,內存,總線,磁盤之間相互協作進行的。首先cpu根據內核數據結構對DMA控制器發送指令,讓它讀取某文件。指令信息包括端口信息,磁盤塊信息,文件偏移量,存儲器地址。然後將這些信息傳給磁盤控制器,磁盤控制器將信息整合後指向到某個扇區,然後將數據讀取到磁盤控制器緩衝區,然後再根據總線上(由DMA控制器寫的)的地址信息,將緩衝區中的數據拷貝到內存當中,當DMA控制器的字節計數器爲0時,向cpu發出中斷操作。然後cpu繼續執行程序中接下來的指令。

 

文中很多東西可能沒有說清楚,本來應該用圖來說明會很清晰的,但是現在不想弄了,先放着,以後有心情的時候來改。寫到這裏我纔想起來,今天是約了人去爬山的。。。悲劇了。

 

本來每個學期我都會將學習和生活記錄下來的,但是這學期實在不想了,平淡的人生無需太多的解釋說明,另外那qq空間早就應該廢了。昨晚我轉輾反側,不寫生活的事情了,怎麼也得寫一篇技術相關的文章來紀念一下這4年的大學生活,所以寫了此文,其實只是總結一些東西而已,可能還總結得不好。

 

還有5天,小弟我將走出華南某理工學校,如果某大神不幸看到此文,請嘴下留情,不吝賜教,我將不勝感激。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章