Linux/Unix分配進程ID的方法以及源碼實現

       在Linux/Unix系統中,每個進程都有一個非負整型表示的唯一進程ID。雖然是唯一的,但是進程的ID可以重用。當一個進程終止後,其進程ID就可以再次使用了。大多數Linux/Unix系統採用延遲重用的算法,使得賦予新建進程ID不同於最近終止進程所使用的ID,這主要是爲了防止將新進程誤認爲是使用同一ID的某個已終止的先前進程。本文討論了Linux/Unix分配進程ID的方法以及源碼實現。

分配進程ID的方法

      在大多數Linux/Unix系統中,生成一個進程ID方法是:從0開始依次連續分配,一直到可以分配的最大的進程ID(不同的系統,這個最大值是不一樣的,比如有些Linux系統是65536)。一旦到達最大值,重新從某個值(不同的系統,這個值也是不一樣的,比如在Mac OS X和HP-UX系統中,這個值是100)開始依次連續查找那些還沒有被使用的ID。這裏分配進程ID的方法,存在潛在的安全問題。因爲可以從系統獲取信息或者提取進程間通信的內容。考慮到安全問題,部分系統可能用其他方法來分配進程ID,比如隨機分配一個進程ID。無論用什麼方法分配進程ID,系統都需要保證每個進程ID是獨一無二的。

Linux系統上分配進程ID的源碼實現

      在Linux系統中,內核分配PID的範圍是(RESERVED_PIDS, PID_MAX_DEFAULT),在每個namespace中,PID是依次連續分配的(在不同的namespace的task可以有相同的ID)。一旦ID達到分配到達上限(在pseudo-file /proc/sys/kernel/pid_max中可以查看可以分配的最大進程ID),從頭開始查找分配PID。以下是相關的源代碼:

struct pid *alloc_pid(struct pid_namespace *ns)
{
	/*省略了一些代碼*/
	for (i = ns->level; i >= 0; i--) {
	    nr = alloc_pidmap(tmp);
	    if (nr < 0)
		goto out_free;
	    pid->numbers[i].nr = nr;
	    pid->numbers[i].ns = tmp;
	    tmp = tmp->parent;
	}
	/*省略了一些代碼*/
}
static int alloc_pidmap(struct pid_namespace *pid_ns)
{
        int i, offset, max_scan, pid, last = pid_ns->last_pid;
        struct pidmap *map;

        pid = last + 1;
        if (pid >= pid_max)
                pid = RESERVED_PIDS;
        /* and later on... */
        pid_ns->last_pid = pid;
        return pid;
}

       注意在Linux內核中,進程PID實現並不僅僅是一個int標識符號(當然返回給應用程序,PID只是int類型的數值)。相關實現的結構體在/include/linux/pid.h中可以找到。除了ID外,它還包括跟這個ID相關的task列表、引用計數器和一個可以方便查找的hashed list。

進程ID分配需要注意的事項
       1、殭屍進程的PID是暫時不能用的,需要其父進程收集器所有的終止狀態才能使用,也就是說需要調用類似wait()函數後,才能使用。
       2、具體實現時,系統可以隨機分配進程PID(當然是保證沒有被其他進程使用),因此在應用程序中,不要依賴於進程PID的分配方式。
       3、在用戶空間(user space)可能看到分配的進程ID並不連續,這是因爲在應用程序兩個fork之間,內核調度程序(scheduling)可能創建了一個進程。事實上,這種情況是經常發生的。

參考資料

《UNIX環境高級編程》(第二版)
http://superuser.com/questions/135007/how-are-pids-generated
http://stackoverflow.com/questions/3446727/how-does-linux-determine-the-next-pid
http://en.wikipedia.org/wiki/Process_identifier


發佈了38 篇原創文章 · 獲贊 17 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章