天天看點

Linux-程序概念馮諾依曼體系作業系統OSPCB-程序描述程序概念系統調用建立程序-fork程序狀态程序間的性質程序優先級環境變量程序位址空間

程序是一個非常重要的概念,了解它,你會更清晰的認知計算機中的程式執行。看待計算機的角度都會不一樣。

  • 馮諾依曼體系
    • 通信在體系下的硬體操作
    • 外設與CPU的互動
  • 作業系統OS
    • 邏輯圖
    • 概括
    • 管理的概念
  • PCB-程序描述
  • 程序概念
    • 建立程序
    • 删除程序
    • PCB的成員
      • 時間片
      • 辨別符
      • 狀态
      • 優先級
      • 程式計數器
      • 記賬資訊
      • 程序切換與排程
      • 上下文資料
      • 結構體指針
    • CPU的操作
  • 系統調用建立程序-fork
  • 程序狀态
    • R狀态(運作狀态)
    • S狀态-休眠狀态
    • D狀态-深度睡眠
    • T狀态-暫停狀态
    • Z-僵屍狀态
    • 孤兒狀态
  • 程序間的性質
  • 程序優先級
    • top任務管理器
      • PRI與NICE值
  • 環境變量
    • 常見的環境變量
      • HOME
      • SHELL
      • env
    • 三個main函數的參數
      • argc-指令行參數個數
      • argv-指令行參數清單
      • envp-環境變量參數清單
  • 程序位址空間
    • 提問:這個程序位址空間是不是記憶體呢?
    • 程序位址空間對應的位址不是實體位址
    • 虛拟位址
      • 邏輯關系
      • 對父程序也一樣
    • 程序位址空間的了解
      • 為什麼會存在程序位址空間
      • 建立程序

馮諾依曼體系

首先,來介紹計算機的結構-馮諾依曼體系

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

這是現代計算機的邏輯結構。

輸入裝置:鍵盤、滑鼠、搖桿、網卡…

輸出裝置:螢幕、硬碟、音響、網卡…

存儲器:記憶體

也就是說,在不考慮緩存的情況下,CPU隻會與記憶體進行互動,輸入輸出裝置也是隻與記憶體(存儲器)進行直接互動。

控制器是進行決策的,決策的對象是記憶體中的資料與代碼。

運算器是根據控制器的指令進行運算。

比如:鍵盤輸入時,鍵盤中的寄存器會進行按鍵識别,識别後會把寄存器的資料給記憶體中相應的寄存器,CPU中的控制器會控制其寄存器中的資料讀到運算器中,在根據指令進行操作。

各種硬體單元,使用的是線:總線(IO總線,系統總線),進行連接配接。

通信在體系下的硬體操作

使用即時通信軟體,例如QQ,微信。

如果兩個人想要發資訊,需要兩個人的QQ都要打開,則意味着,QQ這個程式變成了程序(後面介紹),正在執行中。

A從鍵盤上輸入發送的資訊,資訊被讀取到記憶體中,再被CPU讀取,根據QQ的加密或者資料打包,再還要符合網絡協定的格式,被CPU處理,再放入記憶體中,被輸出裝置(顯示屏,網卡)讀取,資訊原封不動的顯示在顯示器上,同時,被打包後的資訊會被發送進入網絡,伺服器上,

再發送到B的網卡中,資料包再被讀取到記憶體中,被CPU解碼,發送回記憶體,再被顯示器讀取,顯示。就完成了一整個通信的硬體邏輯操作的過程

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

外設與CPU的互動

像輸入輸出裝置也是能與CPU互動的,但不是資料互動,而是信号級别的互動,比如:中斷(外部中斷)

當你在鍵盤上輸入資料時,CPU是如何知道輸入好了資料呢?就是靠外設和CPU之間的信号互動。當資料輸入好了,給CPU(控制器)發送一個硬體級别的電脈沖,CPU就會把外設寄存器中的資料讀入到記憶體中。

除此之外,在資料層面上,CPU是不會和外設進行互動的,因為效率太低了。

所有裝置在資料層面上都隻能和記憶體(存儲器)進行互動。

作業系統OS

一個計算機中,僅僅隻有硬體體系是不夠的,還需要管理硬體,然硬體被組織起來。

是以開發了一款軟體,來對硬體資源進行管理,就是作業系統。同時,作業系統還為其它應用程式提供了一個可執行的軟體環境

邏輯圖

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

其中的驅動,是進行硬體和OS之間處理資訊的,防止不同的硬體導緻OS出現問題,讓OS與硬體進行解耦。

概括

是以說作業系統就是

核心(記憶體管理,檔案管理,程序管理,驅動管理)

其它程式(函數庫,shell程式)

設計OS的目的,是為了

  • 與硬體互動,管理所有的軟硬體資源
  • 為使用者程式(應用程式)提供一個良好的執行環境

純粹是為了進行管理。

管理的概念

我目前還是個學生,對于這個方面還是舉學校的例子。

學生入學後,就進入了學校的管理系統,就屬于被管理這的身份。而我們學生是看不到那些系統裡的資訊的。

而每個學院每一級都有一個輔導員,他負責處理我們的入學生活之類的。他看上去是個管理者,

但站在整個學校的角度來看,校長才是真正的管理者,而我們學生是被管理者,輔導員之類的是執行者。

而校長靠什麼來管理我們的呢?靠教務系統,系統裡已經全部組織好了全校學生的資訊。比如,要打學校之間的辯論賽了,校長在教務系統中挑10名績點最高的學生去打比賽,校長選好後,告訴輔導員,讓輔導員去組織一下賽前準備。這個過程就是一個被組織的過程。

是以可以得出一個概念,管理,其實就是,先描述,再組織的過程。

PCB-程序描述

作業系統對于程序也是要進行管理的,也是要遵循,先描述再組織的過程。

那一個OS要管理的程序肯定不止一個,那那麼多的程序要麼怎麼一一描述?

使用C語言中的結構體的概念,因為linux核心就是那C語言寫的。

關于程序的所有資訊都被放置在一個程序控制塊中的結構體中,結構體中右程序所有資訊的分類。

task_struct
{

}
           

task_struct是Linux核心的一種資料結構,它會被裝載到RAM(記憶體)裡并且包含着程序的資訊

而一個PCB程序控制塊來規劃、組織一個程序,那OS要管理多個程序的時候,就是要管理多個PCB。那OS就會用一個資料結構來管理多個PCB。

使用了連結清單來組織的資料結構。

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間
Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

程序概念

當一個可執行檔案(exe檔案),沒有執行時,是被儲存在硬碟中,當被執行後,這個可執行程式的代碼和資料就會被從硬碟中,加載到記憶體中。

且,當電腦開機時,第一個加載到記憶體中的程序就是作業系統。然後加載到記憶體中的程序就會被作業系統管理起來,管理程序的PCB。

建立程序

可執行檔案的代碼和資料會被加載到記憶體中,同時,OS會為這個程序建立一個PCB結構體來描述這個程序,同時,會把新建立的PCB連接配接到執行連結清單中,等待被CPU讀取。

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

删除程序

當選擇删除時,作業系統會先找到,要被删除程序的PCB,然後根據PCB中的資訊,找到在記憶體中的代碼和資料的位置,将這個記憶體銷毀,再将·PCB從隊列中剔除,并銷毀PCB的所處空間。這就完成了一個程序的删除。

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

PCB的成員

  • 标示符: 描述本程序的唯一标示符,用來差別其他程序。
  • 狀态: 任務狀态,退出代碼,退出信号等。
  • 優先級: 相對于其他程序的優先級-pid。
  • 程式計數器: 程式中即将被執行的下一條指令的位址。
  • Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間
  • 記憶體指針: 包括程式代碼和程序相關資料的指針,還有和其他程序共享的記憶體塊的指針
  • 上下文資料: 程序執行時處理器的寄存器中的資料[休學例子,要加圖CPU,寄存器。
  • I/O狀态資訊: 包括顯示的I/O請求,配置設定給程序的I/O裝置和被程序使用的檔案清單。
  • 記賬資訊: 可能包括處理器時間總和,使用的時鐘數總和,時間限制,記賬号等。
  • 其他資訊

時間片

時間片:由于在計算機中,一定是程序多,CPU少,但是一個CPU不能隻執行一個程序,其它程序也要執行,是以有了時間片的概念,即一個程序在CPU上執行的時間,通常是比較短的,這個程序在CPU上執行一點時間,立馬換下一個程序,就遮掩給,依次進行。在我們看起來1就像是多個程序在同時進行的。

在正常的程序排程的過程中,要基于時間片來進行排程,也就是基于時間片的輪轉

我先聲明一下,這些圖檔都是我在OneNote上做的筆記,但複制就變成了圖檔了。

辨別符

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

狀态

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

優先級

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

程式計數器

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

記賬資訊

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

程序切換與排程

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

上下文資料

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

結構體指針

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

CPU的操作

當程式變成程序時, CPU要對程序進行操作。

CPU隻負責執行三個操作,循環進行。

讀取指令->分析指令->執行指令

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間
Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

這個程序替換就是又作業系統來決定的。

CPU取指令時,要從指令寄存器eip中讀取即将要執行的下一條指令的位址。也就是PCB中程式計數器的概念。

實際上,作業系統對程序的管理,就是對PCB連結清單的增删查改。

再概括一下,作業系統對程序的管理是,先描述,再組織。描述就是建立PCB,組織就是對連結清單進行操作。

系統調用建立程序-fork

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

如果是子程序,其傳回的就是0

如果是父程序,其傳回的就是子程序的pid

如果程序建立失敗,就會傳回-1。

這個是fork函數的傳回值的資訊。

從某種意義上說,這個函數有兩個傳回值。

因為它不僅會傳回代表子程序的0,還有代表父程序的子程序的pid。

至于為什麼說他又兩個傳回值,看這個。

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

這是輸出結果。

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

看到麼?這有兩個傳回值,正好對應了上面的介紹。

這就是可以通過,fork函數系統調用建立子程序,有兩個程序,就可以讓兩個程序執行不同的操作,利用其傳回值。

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

這是效果

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

一直執行不同的操作。

程序狀态

程序再記憶體中也是有狀态的。

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

對于作業系統而言,所有的程序都需要被作業系統識别,區分,而作業系統不能像我們人類能這麼抽像的了解,是以,程序狀态要讓OS了解,就必須符合OS的規則,要将其資料化。

在OS中,程序的所有狀态的都是可以資料化的,

而程序狀态->資料化,所有的資料都被儲存在PCB中,不然PCB怎麼叫程序狀态控制塊。

task_struct

中,就有一個指針數組專門存儲程序的所有狀态。

static const char * const task_state_array[] = {
"R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */
"t (tracing stop)", /* 8 */
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */
};
           
Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

R狀态(運作狀态)

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

舉例

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間
Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間
Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

注意:

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

S狀态-休眠狀态

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

舉例:

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間
比如說:你在課堂上太困了,然後你跟你同桌說,太困了,要睡一覺,等老師來了,就趕緊叫醒你。這時,觸發你醒的條件就是老師來了。然而,這也可以因其他情況叫醒你,比如,老師叫你上去做題目,這又是另外一種條件。或者你自己睡醒了。你是随時能夠被喚醒的。

休眠狀态的程序也是這樣子。

D狀态-深度睡眠

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

可以防止程序被作業系統殺掉,而導緻程序執行任務失敗後造成資源丢失,而記憶體洩漏。

T狀态-暫停狀态

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

經過信号SIGSTOP可以讓程序處于暫停的狀态

這個和休眠狀态很像,按照程式設計需要進行程序暫停或運作。

Z-僵屍狀态

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

一個程序需要一個退出碼,其OS需要根據退出碼來判斷這個程序為什麼退出。是正常退出還是因為其他原因而導緻程序退出。

這個退出碼就是main函數中return傳回的值。

可以用

echo $?

來顯示退出碼。

且這個程序的退出碼儲存在

task_struct

中,也就是PCB中,OS會在這裡讀取退出資訊。

孤兒狀态

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

這是父程序托管子程序的狀态。

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

當我殺掉父程序時,子程序的pid未變動,而父程序已經變成了OS

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

子程序被1号程序接管了。

程序間的性質

  • 獨立性:多程序運作需要獨享各種資源,多程序運作期間互不幹擾
  • 并行:多程序在多個CPU下分别、同時的進行(任意時刻)
  • 并發:多個程序在一個CPU下采用切換的方式,在同一時間段内,多個程序都得以推進
  • 競争:系統程序數目衆多,而CPU資源有限,是以程序之間存在競争性,為了高效完成任務,程序獲得相關資源的先後順序便有了優先級
當程序數目較多時,對某一該程序而言,其切換到周期就變大了,就反映出一種”卡“的感覺

程序優先級

  • cpu資源配置設定的先後順序,就是指程序的優先權(priority)。
  • 優先權高的程序有優先執行權利。配置程序優先權對多任務環境的linux很有用,可以改善系統性能。
  • 還可以把程序運作到指定的CPU上,這樣一來,把不重要的程序安排到某個CPU,可以大大改善系統整體性能。

top任務管理器

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

PRI與NICE值

  • PRI也還是比較好了解的,即程序的優先級,或者通俗點說就是程式被CPU執行的先後順序,此值越小程序的優先級别越高
  • 那NI呢?就是我們所要說的nice值了,其表示程序可被執行的優先級的修正數值
  • PRI值越小越快被執行,那麼加入nice值後,将會使得PRI變為:PRI(new)=PRI(old)+nice
  • 這樣,當nice值為負值的時候,那麼該程式将會優先級值将變小,即其優先級會變高,則其越快被執行
  • 是以,調整程序優先級,在Linux下,就是調整程序nice值
  • nice其取值範圍是-20至19,一共40個級别

需要強調一點的是:程序的nice值不是程序的優先級,他們不是一個概念,但是程序nice值會影響到進 程的優先級變化。

可以了解nice值是程序優先級的修正資料

通過top指令也能修改一個程序的NICE值,來間接修改一個程序的優先級。

top->按 ‘r’ -> 輸入程序的PID - >輸入NICE值
Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

通過

ps -al

可以檢視程序

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

我把子程序的優先級修改成了60,也就是說我将NICE值變成了-20,是以子程序的優先級是最高的。

提醒:普通權限是不被允許修改程序優先級的,要sudo提升權限。才會允許。

環境變量

  • 環境變量(environment variables)一般是指在作業系統中用來指定作業系統運作環境的一些參數

    如:我們在編寫C/C++代碼的時候,在連結的時候,從來不知道我們的所連結的動态靜态庫在哪裡,但是照樣可以連結成功,生成可執行程式,原因就是有相關環境變量幫助編譯器進行查找。

  • 環境變量通常具有某些特殊用途,還有在系統當中通常具有全局特性

由系統提供的環境變量,那就有變量名與變量内容。

如,經常使用的

ls

指令,這其實某種程度上說是一個可執行程式。就跟我們讓自己寫的程式運作。

一般是

./myproc

.

是指在目前目錄下查找,找到

myproc

後,再執行。而

ls/mkdir/rm/mv....

都是一樣的,要先找到,在執行這個程式。這些查找其路徑,就是靠環境變量來完成。

常見的環境變量

  • PATH : 指定指令的搜尋路徑
  • HOME : 指定使用者的主工作目錄(即使用者登陸到Linux系統中時,預設的目錄)
  • SHELL : 目前Shell,它的值通常是/bin/bash。

ls

指令就是PATH去指定指令下搜尋。

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

就會去這些路徑下搜尋指令。

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間
Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

ls指令是被打包後的。

從理論上說,隻要我們把自己編寫的可執行程式也放入PATH可以找到的路徑下,那麼也能像這些指令一樣運作。

比如:

sudo cp -f myproc /usr/bin

(不推薦,可能會對系統造成影響)

export PATH=$PATH:可執行檔案的路徑
           

這樣就是添加了PATH查找的路徑

如果你破壞了環境變量,也沒什麼,重新進一下系統,伺服器會重新配置環境變量的。

HOME

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

可以顯示自己所處的工作目錄。也就是說這個環境變量儲存了目前所處的工作目錄

SHELL

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

顯示指令行解釋器的版本

env

可以顯示所有的環境變量

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

三個main函數的參數

argc-指令行參數個數

argv-指令行參數清單

envp-環境變量參數清單

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間
Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

後面的就是指令行參數。

解釋一下:

ls -a/-al...

這些都是指令,而 ls 是指令,而後面的-a -al 都是選項

就有點像,函數傳遞的不同的參數,而執行不同的指令
Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

最後一個元素是NULL代表結尾。

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間
Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

代碼運作後

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間
Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

把環境變量全部給列印出來了。

如果把這個程式加入PATH中,就也能變成一個指令。

程序位址空間

先來回顧一下程式位址空間。

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

我們曾經認為的程式空間的位址就是這樣,可以直接對應與硬碟的空間。系統給程式配置設定了

2的32次方

(32位機下)的大小,總共4G,當時我還不了解是什麼意思。

現在,在了解了程序後,這個其實是叫程序位址空間更合适一些。

提問:這個程序位址空間是不是記憶體呢?

回答:不是(後面解答)

程序位址空間對應的位址不是實體位址

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

這是一份程式,還沒跑起來。有一個全局變量

val

,在父程序時,讓該程序休眠了1秒,也就是說讓子程序先跑。

在子程序的分流中執行了修改全局變量的值。

看看輸出結果。

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

子程序修改後的val的值變成20了,而父程序的值依舊是之前的100,而兩個程序分流後的val的位址依舊是一樣的,沒有改變

也就是說,val的位址沒變,但是子程序與父程序的val值取已經發生了改變。看似不可能,卻是實實在在的發生了改變。

先前提過,父程序建立了子程序,子程序會共享父程序的代碼和資料。

這也就證明了一點,這個程序位址空間,其對應的位址,根本就不是真實的實體位址,如果其對應的是真實的實體位址,那麼兩個位址一樣的空間,是不可能讀取到兩個不同的值

虛拟位址

程序位址空間對應的位址,其實是虛拟位址。也就是說,我們在代碼中操作的指針、位址,也不是真實位址,而也是虛拟位址。

而在Linux作業系統中,OS負責将實體位址轉換為虛拟位址。

再來一個聯想,列印輸出的val的虛拟位址在父子程序中是一樣的,而值是不一樣的也就是說,這個val的真實實體位址是不一樣的,隻不過作業系統将不同的實體位址處理成了相同的虛拟位址。

邏輯關系

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

頁表是OS處理虛拟與實體位址之間映射關系的方案,頁表使用一種算法,将實體位址處理成虛拟位址,且,讓實體位址不可見。同時對于子程序也是一樣的。

當程式運作時,子程序的分流修改了val的值,由于程序之間是具有獨立性的,子程序的資料被修改了,并不會影響父程序的資料。為了保證這種程序間的獨立性,OS會位這個val在記憶體中申請過一個空間,修改val的值,同時,這個新申請的空間的位址就又會被頁表處理,使虛拟位址不變。

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

對父程序也一樣

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

這次,我讓父程序先運作,先對val的值進行修改,子程序後運作。看看結果。

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

同樣,為了滿足程序之間的獨立性,并不是隻有子程序會讓OS為它在其它地方申請一塊空間來儲存修改後的值,對于任何程序都一樣,無論是父程序還是子程序。

Linux-程式概念馮諾依曼體系作業系統OSPCB-程式描述程式概念系統調用建立程式-fork程式狀态程式間的性質程式優先級環境變量程式位址空間

程序位址空間的了解

其本質是記憶體中的一種資料結構

mm_struct

也就是意味着,結構體成員中存在不同的區域,而程序位址空間中存在不同的區域,靜态區,代碼區,資料區,堆區,棧區…

而這些被

mm_struct

這個結構體進行維護,是以說,結構體中就存在

stack_start、stack_end、heap_start、heap_end

差不多是這樣的成員。

而了解上,程序位址空間是實體記憶體的一種度量。實體記憶體本身是不具備任何衡量标準的,隻是代表一個個位址,而程序位址空間,就像是一把尺子上的刻度,将實體記憶體邏輯化、形象化、資料化了。

不僅僅是記憶體被劃分區域了,對于磁盤中的程式,可執行檔案(Linux中是ELF檔案),也同樣被劃分了不同的區域,代碼段,資料段…當這個檔案被執行時,會根據規則,将這些分段全部連結在一起。

為什麼會存在程序位址空間

  1. 有了程序位址空間提供的虛拟位址、虛拟空間,這樣可以防止代碼中有些操作直接通路實體位址,這樣,哪怕是通路了未申請區域,也僅僅是虛拟空間中的越界,,不會存在系統界别的越界通路,在虛拟空間中,作業系統是可以掌握的,最多就是代碼執行出錯,系統殺程序或者程序崩了,不會影響到真實的實體記憶體。同時,頁表可以對真實的實體位址進行保護,讓真實的實體位址完全不可見,可以保護記憶體。
  2. 大一統的好處:讓所有的程序都遵循同一個處理規則,所有的程序都有着相同的記憶體處理規則
  3. 每個程序都認為自己是獨占記憶體的,更好的完成程序的獨立性且合理的配置設定空間,友善作業系統合理的規劃所有控件的排程。
因為一個程序不可能是所有的代碼資料都同時加載到記憶體中,因為記憶體明顯不夠,且把CPU是一條指令一條指令的執行,一次性把所有代碼和資料都加載到記憶體中,大部分的代碼和資料并不會被執行,這樣非常占用資源,是以,排程算法會處理,當需要執行的部分,才會進行加載,配置設定資源空間。這樣作業系統可以很高效的配置設定資源。

将程序排程和記憶體管理進行解耦分離對于部分的程序排程,隻有當執行到的時候才會為其配置設定資源,減少記憶體負荷。

建立程序

繼續閱讀