1. 程式人生 > >CSAPP:第八章 異常控制流2

CSAPP:第八章 異常控制流2

[] 定義 一段時間 meta onos 進程組 clu ESS 基於

CSAPP:第八章 異常控制流2

關鍵點:進程控制、信號

8.4 進程控制8.5 信號

8.4 進程控制

??Unix提供了大量從C程序中操作進程的系統調用。
8.4.1 獲取進程ID
??每個進程都有一個唯一的正數(非零)進程ID(PID)。getpid函數返回調用進程的PID,getppid函數返回它父進程的PID

1#include <sys/types.h>
2#include <unistd.h>
3pid_t getpid(void);
4pid_t getppid(void);
5#pid_t 在Linux系統的types.h中定義為int

8.4.2 創建和終止進程


??從程序員角度,我們可以認為進程總是處於下面三種狀態之一:

  • 運行。進程要麽在CPU上執行,要麽在等待被執行且最終會被CPU內核調度。
  • 停止。進程的執行被掛起,且不會被調度。當收到SIGSTOP、SIGTSTP、SIGTTIN或者SIGTTOU信號時,進程就停止,並且保持停止直到它收到一個SIGCONT信號,在這個時候,進程再次運行。
  • 終止。進程永遠地停止了。進程會因為3種原因終止:1)收到一個信號,該信號的默認行為是終止進程;2)從主程序返回;3)調用exit函數。
1#include <stdlib.h>
2void exit(int status);
3exit函數以status退出狀態來終止進程

??父進程通過調用fork函數創建一個新的運行子進程。

1#include <sys/types.h>
2#include <unistd.h>
3pid_t fork(void);

??子進程得到與父進程用戶級虛擬地址空間相同的(但是獨立的)一份副本,包括代碼和數據段、堆、共享庫以及用戶棧。子進程還獲得與父進程任何打開文件描述符相同的副本。父進程與子進程最大的區別是它們有不同的PID。
??fork函數被調用一次,卻會返回兩次:一次調用進程(父進程)中,一次是在新創建的子進程中。在父進程中fork返回子進程的PID。在子進程中fork返回0
8.4.3 回收子進程
??當一個進程由於某種原因終止時,內核並不是立即把它從系統中清除。相反,進程被保持在一種已終止的狀態中,直到被它的父進程回放(reaped)。當父進程回收已經終止的子進程時,內核將子進程的退出狀態傳遞給父進程,然後拋棄已終止的進程,從此時開始,該進程就不存在了。一個終止了但還沒被回收的進程稱為僵死進程。
??如果一個父進程終止了,內核會安排init進程成為它的孤兒進程的養父。init進程的PID為1,是在系統啟動內核創建的,它不會終止,是所有進程的祖先。如果父進程沒有回收它的僵屍子進程就終止了,那麽內核會安排init進程取回收它們。
??一個進程可以通過調用waitpid函數來等待它的子進程終止或者停止。

1#include <sys/types.h>
2#include <sys/wait.h>
3pid_t waitpid(pid_t pid, int *statusp,int options);
4//返回:如果成功,則為子進程的PID,如果WNOHANG,則為0;如果其他錯誤則為-1.

8.4.4 讓進程休眠
??sleep函數將一個進程掛起一段時間

1#include <unistd.h>
2unaigned int sleep(unsigned int sec);
3//如果請求到了返回0,否則返回還剩下休眠時間的秒數

8.4.5 加載並運行程序
??execve函數在當前進程的上下文中加載並運行一個新程序。

1int execve(const char*filename,const char *argv[],const char*envp[]);
2execve執行可執行目標文件filename,且帶參數列表argv和環境變量列表envp

8.5 信號

??一個信號就是一條小道消息,它通知進程系統中發生了某種事件

技術分享圖片
8.5.1 信號術語

  • 發送信號
  • 接收信號
    8.5.2 發送信號
    ??Unix系統提供了大量向進程發生信號的機制。所有機制都是基於進程組的概念。每個進程都只屬於一個進程組,進程組是由一個正整數ID來標識。
  • 用bin/kill程序發生信號
  • 從鍵盤發生信號
  • 用kill函數發生信號
  • 用alarm發送信號
    8.5.3 接收信號
    ??每個信號類型都有一個預定的默認行為,是下面的一種:
  • 進程終止
  • 進程終止並轉儲內存
  • 進程停止(掛起)直到被SIGCONT信號重啟。
  • 進程忽略該信號
1#include<signal.h>
2typedef void (*sighandler_t)(int);
3sighandler_t signal(int signum,sighandler_t handler)

??signal通過以下三種方法之一來改變和信號signum的關聯行為:

  • 如果handler為SIG_IGN,那麽忽略類型為signum的信號
  • 如果handler是SIG_DFL,那麽類型為signum的信號行為恢復為默認行為
  • 否則,handler就是用戶定義的函數地址,這個函數稱為信號處理程序。調用信號處理程序被稱為捕獲信號。執行信號處理程序被稱為處理信號。

CSAPP:第八章 異常控制流2