天天看點

【初探】作業系統之程序線程作業系統之程序線程

  • 日期:20160606
  • 作者:i.sshe
  • https://github.com/isshe

作業系統之程序線程

1. 問題清單

  • 1.1 什麼是程序?什麼是線程?
  • 1.2 程序的基本狀态及轉換?
  • 1.3 程序控制塊(PCB)?
  • 1.4 程序的運作模式有哪些?
  • 1.5 程序間是如何通信的?
  • 1.6 系統如何将一個信号通知給程序?
  • 1.7 32/64位系統一個程序最多能擁有多少堆記憶體?
  • 1.8 如何實作守護程序?
  • 1.9 線程控制塊(TCB)?
  • 1.10 線程有哪些狀态?
  • 1.11 線程為什麼沒有挂起狀态?
  • 1.12 什麼是使用者級線程?什麼是核心級線程?有何優缺點?
  • 1.13 程序和線程的差別?
  • 1.14 線程中可以建立線程嗎?
  • 1.15 線程中可以建立程序嗎?
  • 1.16 線程的同步機制有哪些?
  • 1.17 什麼是僵屍程序?什麼是孤兒程序?

2016.11.1補充

* 1.18 fork後,子程序繼承父程序的什麼,父、子程序差別?

2. 拓展問題

  • 2.1 什麼是上下文?上下文切換又是什麼?
  • 2.2 堆和棧的差別?
  • 2.3 試解釋作業系統原理中的作業、程序、線程、管程的定義?

3. 解答

3.1 什麼是程序?什麼是線程?

  • 程序
    • 定義:一個執行中的程式的執行個體.
    • 是一個可擁有資源的獨立機關;
    • 是作業系統對一個正在運作的程式的抽象;
    • 是計算機科學中最重要最成功的一個概念;
    • 在一個系統上可以上可以同時運作多個程序;
  • 線程
    • 排程和分派的基本機關;(隻有一些必要的資源,是以也稱為"輕型程序")
    • 一個程序内可以建立多個線程;(每個線程都運作在程序的上下文中,并共享的代碼和全局資料)

3.2 程序的基本狀态及轉換?

  • 三種基本狀态:
    • 就緒狀态(Ready). 資源什麼的已經準備好了,隻要得到處理機就可進入執行狀态.
    • 執行狀态(Running).
    • 阻塞狀态(Block). 資源沒有得到滿足.
  • 引入的狀态:
    • 建立狀态.
    • 終止狀态.
    • 挂起狀态.(下圖沒有畫進去)
  • 狀态間的轉換:
    • 【初探】作業系統之程式線程作業系統之程式線程

3.3 程序控制塊(PCB)

  • 程序控制塊:作業系統維護的一張程序表.
  • 包含的一些字段:
    • 程序管理: 寄存器, 程式計數器,程式狀态字, 堆棧指針, 程序狀态, 優先級, 排程參數, 程序ID(唯一), 父程序, 程序組, 信号, 程序的開始時間, 使用的CPU時間, 子程序的CPU時間, 下次報警時間.
    • 存儲管理: 正文段指針, 資料段指針, 堆棧段指針.
    • 檔案管理: 根目錄, 工作目錄, 檔案描述符, 使用者ID, 組ID.

3.4 程序的運作模式有哪些?

  • 【初探】作業系統之程式線程作業系統之程式線程
  • 程序的工作模式有兩種: 核心模式(态)和使用者模式(态).
  • 處理器通常通過模式位(mode bit)來設定程序運作模式,設定模式位的時候運作在核心模式, 否則運作在使用者模式.
  • 使用者模式到核心模式的方法:
    • 中斷
    • 故障
    • 陷入系統調用
  • 核心模式到使用者模式:
    • 處理程式運作在核心模式中,當它傳回到使用者程式代碼時,就會切換.

3.5 程序間是如何通信的?

  • Linux支援的程序間通信機制包括:管道,信号,消息隊列,記憶體共享, 快速使用者空間互斥體(futex:fast userspace mutex)等。
  • http://blog.csdn.net/i_scream_/article/details/51619428

3.6 系統如何将一個信号通知給程序?

  • 信号是軟體中斷!
  • 當系統檢測到某軟體條件(如SIGURG, SIGPIPE, SIGALRM等,因為是軟體中斷,是以是軟體條件)發生時,将其對應的信号通知給有關程序,并執行特定操作(注冊信号時指定的操作)。

3.7 32/64位系統中, 一個程序分别最多能擁有多少堆記憶體?

  • 不懂。
  • 網上一種說法是:32位系統中,最大堆記憶體約等于虛拟記憶體減1G;

3.8 如何實作守護程序?

  • 程式設計規則:(unix環境進階程式設計P374)
    • 首先,調用umask将檔案模式建立屏蔽字設定為一個已知的值(通常是0);
    • 調用fork(),再exit父程序;
    • 調用setsid建立一個新會話;
      • 這裡會發生三件事:
        • 程序成為新會話的首程序;
        • 程序成為新程序組的組長程序;
        • 程序沒有控制終端;
    • 将目前工作目錄更改為根目錄;(因為從父程序繼承過來的目錄可能在一個挂載的檔案系統中,如果不更改為根目錄,則所挂載的檔案系統不能解除安裝)
    • 關閉不需要的檔案描述符;
    • 某些守護程序打開/dev/null使其具有檔案描述符0, 1, 2。(守護程序不需要互動式輸入/輸出)

3.9 線程控制塊(TCB)

  • 每個線程都有自己的線程控制塊(TCB),包括:
    • 線程ID(TID,唯一,整數)
    • 棧(如同非線程系統上的程序棧,主要存局部變量,參考…[此處有位址….])
    • 棧指針
    • 程式計數器
    • 通用目的計數器
    • 條件碼(即各種狀态标志)
  • 所有運作在一個程序裡的線程共享整個虛拟位址空間.(代碼段開始虛拟位址為0x00400000[64bit], 0x08048000[32bit])
  • 共享程序的代碼段,資料段.

3.10 線程有哪些狀态?

  • 線程和程序都有三個基本狀态.且情況一樣.

3.11 線程為什麼沒有挂起狀态?

  • 挂起: 将資源從記憶體移動到外存.
  • 線程不擁有資源,不管理資源,是以它應有将整個程序或自己本身從主存移動到外存的權限.

3.12 什麼是使用者級線程?什麼是核心級線程?有何優缺點?

1). 使用者級線程(ULT)

  • 由使用者應用程式建立,排程,管理, 作業系統不知道使用者級線程的存在.
  • 優點:
    • 轉換的時空開銷比核心級線程小得多;
    • 線程的排程算法和作業系統的排程算法無關;
    • 适用于任何作業系統, 因為它與核心無關;
  • 缺點:
    • 無法利用多處理器的優點, 每次隻有一個程序的一個線程在一個CPU上運作.

2). 核心級線程(KLT)

  • 所有線程的建立,排程,管理都由作業系統核心負責.
  • 優點
    • 核心可排程一個程序中的多個線程, 可利用多處理器的優點.(同時在多個處理器上運作,提高程式的執行速度和效率);
    • 當一個程序中的一個線程被阻塞,程序中的其他線程仍可執行;
    • 核心本身也可以以線程的方式實作;
  • 缺點:
    • 線程切換時空開銷大:同一個程序中的線程切換需要兩次模式轉換(使用者态->核心态->使用者态),因為線程排程程式運作在核心态,使用者應用程式運作在使用者态.

3.13 程序和線程的差別?

  • 排程:
    • 線程是排程和指派的基本機關; 程序是擁有資源的基本機關;
    • 同一程序中,線程切換不會引起程序切換; 不同程序中, 線程切換會引起程序切換.
  • 擁有資源:
    • 線程不擁有系統資源,但可以通路隸屬程序的系統資源.
    • 程序擁有資源
  • 并發性:
    • 線程具有更好的并發性
  • 切換開銷:
    • 線程開銷更小,因為隻需儲存和設定少量寄存器的内容.
  • 通信:
    • 同一程序内的多線程通信更容易實作,但也容易出錯.

3.14 線程中可以建立線程嗎?

  • 可以。
  • 當一個程式啟動時,就有一個程序被作業系統(OS)建立,與此同時一個線程也立刻運作,該線程通常叫做程式的主線程(Main Thread)。不知是否所有作業系統都适用?

3.15 線程中可以建立程序嗎?

  • 可以。程式開始的時候就會建立一個主線程用于執行代碼。
  • 如果線程中用exec系列的函數,則整個程序被替換。
  • 如果線程用fork(),則可以。

3.16 線程的同步機制有哪些?

http://blog.csdn.net/i_scream_/article/details/51619428

3.17 什麼是僵屍程序?什麼是孤兒程序?

  • 孤兒程序:一個父程序退出,而它的一個或多個子程序還在運作,那麼那些子程序将成為孤兒程序。孤兒程序将被init程序(程序号為1)所收養,并由init程序對它們完成狀态收集工作。
  • 僵屍程序:一個程序使用fork建立子程序,如果子程序退出,而父程序并沒有調用wait或waitpid擷取子程序的狀态資訊,那麼子程序的程序描述符仍然儲存在系統中。這種程序稱之為僵屍程序。

3.18 fork後,子程序繼承父程序的什麼,父、子程序差別?

  • APUE p185
  • 繼承:
    • 讀寫鎖、條件變量、互斥量(這行自己加的、不知道該歸哪類)
    • 實際使用者ID、實際組ID、有效使用者ID、有效組ID。
    • 附屬組ID
    • 打開檔案
    • 會話ID
    • 控制終端
    • 設定使用者ID标志、設定組ID标志
    • 目前工作目錄
    • 根目錄
    • 檔案模式建立屏蔽字
    • 信号屏蔽和安排
    • 對任一打開檔案描述符的執行時關閉(close-on-exec)标志
    • 環境
    • 連接配接的共享存儲短
    • 存儲映像
    • 資源限制
  • 父、子程序差別:
    • fork的傳回值不同
    • 程序ID不同
    • 子程序的tms_utime、tms_stime、tms_cutime和tms_ustime的值設定為0(8.17節)
    • 子程序不繼承父程序設定的檔案鎖。!!!
    • 子程序的未處理鬧鐘被清除。
    • 子程序的未處理信号集設定為空集。

4. 拓展解答

4.1 什麼是上下文?上下文切換又是什麼?

  • 作業系統保持跟蹤程序運作所需的所有狀态資訊,這種狀态,稱為上下文.
  • 無論是在單核還是多核系統中,一個CPU看上去像是在并發地執行多個程序,這是通過程序切換實作的.作業系統把這種交錯執行的機制稱為上下文切換.

4.2 堆和棧的差別

  • 堆(從低位址往高低至增長): 所使用的局部變量還是在棧上,内容則在堆上.手動釋放或者程式結束時由作業系統釋放回收.
    • 由程式員配置設定管理[new/malloc/realloc/calloc].
  • 棧(從高位址往低位址增長): 局部變量/局部常量(const)[局部隻讀變量]/函數調用時傳回位址/調用者的環境資訊(例如某些機器寄存器).
    • 由編譯器自動配置設定釋放管理.
  • 關于C/C++程式運作時程序的記憶體分布情況

4.3 試解釋作業系統原理中的作業、程序、線程、管程的定義?

  • 作業:使用者在一個事務處理過程中要求計算機系統所做的工作的集合。包括使用者程式、資料、控制指令等,作業是由一系列有序的步驟組成的。
  • 程序:一個程式在一個資料集合上的一次運作過程。
  • 線程:程序中的一個實體,是被系統獨立調用和執行的基本機關。
  • 管程:一個資料結構+在該結構上能為并發程序所執行的一組操作,這組操作能同步程序和改變管程中的資料。

5. 零碎的概念/知識

  • 排程: 核心可以決定搶占目前程序, 并重新開始一個先前被搶占的程序, 這種決定叫排程.由核心中呗稱為”排程器”的代碼完成.
  • 父程序ID為0的各程序通常是核心程序(0代表核心),它們作為系統引導裝入過程的一部分啟動。
  • linux中,程序和線程的執行效率是基本相當的。(程序隻比線程多了個COW(copy on write)的開銷)
  • COW技術:寫時拷貝。子程序和父程序要更改記憶體頁面時,再拷貝一份給子程序,否則子程序和父程序共享資源。(也就是拷貝之前相當與線程!)

6. 參考資料

6.1 《深入了解計算機系統》

6.2 《計算機作業系統(第四版)》

6.3 《linux就是這個範》

繼續閱讀