讀書筆記-APUE第三版-(8)進程式控制制

來源:互聯網
上載者:User

標籤:blog   http   使用   strong   檔案   os   

進程ID

每一個進程都有一個唯一的進程ID。幾個特殊進程:

  1. 0號進程是核心進程,一般是調度進程swapper。
  2. 1號進程init,是使用者進程(以root許可權執行/sbin/init),負責初始化。
  3. 幾個重要函數:getpid(進程ID)/getppid(父進程ID)/getuid(進程真有使用者ID)/geteuid(進程有效使用者ID)/getgid(進程真有使用者組ID)/getegid(進程有效使用者組ID)。

fork/exec/wait常式

fork家族函數用於建立子進程(父子進程關係下節詳細介紹),子進程往往調用exec家族函數運行新程式(fork+exec操作在有些系統中被稱為spawn孵化),而wait家族函數用於擷取子進程終止狀態。

system函數使用/bin/sh運行命令,下面是使用fork/exec/wait實現的簡單版本號碼

#include<sys/wait.h>#include<errno.h>#include<unistd.h>int system(constchar *cmdstring) /* version without signal handling */{    pid_t pid;    int status;    if (cmdstring == NULL)        return(1); /* always a command processor withUNIX */    if ((pid = fork()) < 0) {        status = -1;    } else if (pid == 0) { /* fork傳回值為0,表示是在子進程中*/        execl("/bin/sh", "sh","-c", cmdstring, (char *)0);        _exit(127); /* execl error */    } else { /* 在父進程中,fork返回子進程pid */        while (waitpid(pid, &status, 0) < 0) {            if (errno != EINTR) {                status = -1; /* error other than EINTR fromwaitpid() */                break;            }        }    }    return(status);}

  1. fork函數一次調用,在父進程和自己成中兩次返回,由於父進程能夠fork多個子進程,所以設計成在父進程中返回子進程pid,而在子進程返回0,由於子進程能夠通過getpid和getppid擷取自身pid和父進程pid。常見應用情境是在網路編程中,父進程while迴圈監聽使用者請求,當接收到使用者請求,fork出子進程進行處理。註:linux系統中,fork通過clone系統調用實現。
  2. waipid函數使用參數0等待指定子進程返回,wait函數家族包含wait(等待任一子進程返回)/waitpid(等待指定子進程&組返回,並能通過第三個參數設定堵塞選項)/waittid(進一步擴充,能擷取導致進程終止的訊號資訊等)/wait3(還能夠返回進程使用的資源)/wait4(其它wait函數的入口)。
  3. exec家族函數的作用是替換掉當前進程上下文(text/data/heap/stack等),運行新的程式(不會建立新進程)。exec家族函數包含execl/execlp/execle/execv/execvp/execve,各個函數主要差別在參數上,當中l表示是列表形式,v表示是指標數組形式,e表示環境變數,p表示命令參數是相對路徑,會在PATH路徑中搜尋。

父子進程

子進程和父進程共用僅僅讀的text段,針對bss段、對、棧,現代作業系統使用COW(copy-on-write)技術,僅僅有發生改變時,才會拷貝對應的記憶體頁。

父子進程關係

子進程會繼承父進程的大量屬性,當中一些重要屬性包含:真實/有效使用者資訊,進程組/會話資訊,工作資料夾,環境變數,資源限制等。

父子進程最明顯的差別是:子進程的tms時間統計資訊被清零,子進程不會繼承檔案鎖,未決鬧鐘&訊號等(興許章節討論)。

子進程和父進程返回先後順序是不確定的,假設使用者程式對父子進程運行順序有依賴,須要自行處理,比方使用訊號實現等待通知機制等。

  1. 核心為每一個正在終止的進程保留了少量資訊(pid,終止狀態,CPU時間等),便於父進程擷取其終止狀態。
  2. 假設子進程在父進程之前結束,而父進程沒有wait,子進程會變成殭屍進程。
  3. 假設父進程先結束,子進程的父進程會變成init進程(pid為1),所以假設要避免殭屍進程的產生,能夠兩次調用fork,即在子進程中再次調用fork,然後退出。這樣第二個fork出來的進程因為其父進程退出,所以被init進程接管。

檔案分享權限設定

子進程會dup父進程開啟的檔案描寫敘述符(共用檔案描寫敘述符close-on-exec標記),包含標準輸出、輸入和錯誤輸出。


,父子進程共用file tableentry,位置位移量一致,所以要父子進程讀寫同一檔案時要注意同步。

設定進程使用者ID

之前提到,子進程會繼承父進程的uid和euid(有效使用者ID),能夠調用setuid(setgid)改動進程使用者(組)。

  1. 假設是root使用者調用,會同一時候改動進程的uid、euid和備份euid(saved set-user-id)。登陸後,由login(root進程)設定使用者ID。
  2. 非root使用者僅僅能改動euid,並且僅僅能改動成之前的uid或者備份euid,否則出錯。
  3. 假設自進程運行exec方法,並且運行程式的set-user-ID位被設定,那麼euid被設定被運行程式屬主ID。
  4. 備份euid複製euid。正常情況下,uid=euid=備份euid。
  5. 程式編寫遵循“最小許可權“模型,若且唯若程式須要高許可權時,才調用setuid提升許可權,操作完之後再調用setuid恢複許可權。

其它進程相關函數

  1. 進程審計:acct開啟進程審計功能,系統記錄已終止進程的統計資訊,包含使用者ID,啟動時間,CPU時間等。Linux系統審計記錄儲存在/var/log/account/pacct,須要用fread讀取acct結構體資訊。
  2. 進程調度:進程調整nice值來設定執行優先順序(你越nice,你的優先順序越低,人艱不拆。。),相關函數:nice/getpriority/setpriority
  3. 進程時間:調用clock_t times(structtms *buf )函數,當中返回值為時鐘時間,而tms結構體被下面內容填充:

struct tms {    clock_t tms_utime; /* user CPU time */    clock_t tms_stime; /* system CPU time */    clock_t tms_cutime; /* user CPU time, terminated children */    clock_t tms_cstime; /* system CPU time, terminated children */};

注意:相關時間已經通過每秒滴答數(_SC_CLK_TCK)轉化成了秒數,但它是從過去任一時間開始統計的,所以其絕對值無意義。一般分別在進程開始和結束調用times,再計算之間的時間差。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.