工作中剛開始接觸Linux,基本上編程練手就從多線程Demo開始。首先由於對於進程、線程這些基本概念進行了簡單的認知。
1.程序的認識
程序:硬盤中的二進制文件
通常意義上就是我們電腦本地保存的一些文件。比如我電腦上安裝好了一個QQ程序,現在它就躺在我的電腦硬盤中,我沒有去啟動它。這時就叫做一個程序。
2.進程的認識
進程: 加載到內存中的二進制文件 + PCB
現在我運行QQ,計算機會將程序文件從硬盤加載到系統內存中然后執行。這時QQ進程啟動了,可以查看 任務管理器 中QQ這個進程就存在。
進程啟動之后,所有的數據都加載到內存中。比如我們Linux編譯生成一個可執行的
計算機系統啟動了一個進程,那就需要去時時刻刻的管理這個進程,以便於去響應這個進程和進程結束之后的回收工作。
系統在新建一個進程的時候,會給這個進程分配 資源 和 進程控制塊(PCB)。具體情況如下:
Linux系統啟動一個進程,會為該進程分配一個 虛擬地址空間。
1) 對於32位系統,尋址指針為4字節,對應的虛擬地址空間為0 ~ 2^32,即 0-4G
2) 對於64位系統,尋址指針為8字節,對應的虛擬地址空間為0 ~ 2^64,即0-16G

圖2.1 虛擬地址空間
2.1 虛擬地址和虛擬內存、物理內存的概念
物理內存:【跳轉:參考鏈接1】
簡單說使用角度,就是你這個計算機插的內存條是多大的,那么這就是他的物理內存。
CPU中的概念,物理內存就是CPU的地址線可以直接進行尋址的內存空間大小。
比如8086只有20根地址線,那么它的尋址空間就是1MB,我們就說8086能支持1MB的物理內存,即使我們安裝了128M的內存條在板子上,我們也只能說8086擁有1MB的物理內存空間。
同理,32位的CPU就可以支持最大4GB的物理內存空間了;64位的CPU就可以支持最大16GB的物理內存空間了。所以想給電腦加內存條也不是可以隨便加的。
虛擬內存:
從名字上看,“虛擬”的一塊內存。實際上只是一種內存管理手段。
以上面的進程創建時的4G虛擬內存舉例,並不是真的從計算機的物理內存中分配一塊連續的4G內存空間給這個新建的進程使用。如果這樣的話,咱們的32位計算機總共就4G大的物理內存,你要是啟動個幾十個進程不就把計算機的物理內存擠滿了。
事實上,在每個進程創建加載時,內核只是為進程“創建”了虛擬內存的布局,實際上並不立即就把虛擬內存對應位置的程序數據和代碼(比如.text .data段)拷貝到物理內存中,只是建立好虛擬內存和磁盤文件之間的映射(叫做存儲器映射),等到運行到對應的程序時,才會通過缺頁異常,來拷貝數據進入物理內存。
2.2 進程控制塊 PCB
就像是生了孩子就得一輩子管着他、操心他一樣。那么問題來了,你肯定是操心自己家的孩子,不會去操心一個陌生的孩子,因為自己孩子肯定自己認識。那么系統是通過什么來標志、識別這個運行中的進程呢?---- 就是 PCB
內核區的進程控制PCB 會攜帶該進程的一些信息(如:進程狀態、進程標識.......),是系統感知該進程的唯一標識。Linux內核的進程控制塊是 task_struct結構體。【跳轉:參考文章鏈接1】
圖1.2 PCB結構體
3. 線程的認識
線程:是cpu調度的最小單位。
一個進程啟動之后,可以在這個進程中創建多個新的子線程。然后這個進程就退化成了一個線程(稱:主線程)。這樣該進程在運行時,就是主線程和被創建的多個子線程去輪流爭取CPU的時間片,執行各自線程中的處理動作。所以我們說 線程是cpu調度的最小單位。
3.1 進程和線程的差異
(1)進程:是資源分配的基本單位。
前面提到,系統在創建一個進程時會為這個進程分配一定的資源。但是在新建線程時並沒有再為這些個線程再次分配資源。所以新建的多個子線程共用該進程的地址空間。
(2)進程之間是相互獨立的。而線程間是有資源依賴關系的。
例如,我們在一個父進程中,新建了多個子進程。在運行時,任何一個進程的終止,不會影響到其他進程。
在一個主線程中,新建了多個子線程。在運行時,主線程終止,創建的全部子線程被迫終止(因為主線程結束,系統回收了進程資源,這些線程沒有了資源自然無法正常運行)。