歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

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

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

Linux下的進程詳解 http://www.linuxidc.com/Linux/2014-04/99472.htm

分配進程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://www.linuxidc.net/thread-2063-1-1.html

Copyright © Linux教程網 All Rights Reserved