Windows XP 進程 PID 的範圍?為什麼會出現特別大的 PID?

本人在開發一個 Windows XP 的軟體,需要獲取進程 PID,然而今天一次測試時突然發現 PID 居然有 120000 左右,導致程序溢出了。以前從來沒有見過這麼大的 PID,而且之前的測試中,這個進程的 PID 也在正常範圍。為什麼會出現這樣的情況?


你之間見過的天鵝都是白的,不能說明所有的天鵝都是白的。。

至於為什麼大部分天鵝都是白的,Raymond Chen 有個簡短的解釋:因為黑的看著難看。

"I later learned that the Windows NT folks do try to keep the numerical values of process ID from getting too big. Earlier this century, the kernel team experimented with letting the numbers get really huge, in order to reduce the rate at which process IDs get reused, but they had to go back to small numbers, not for any technical reasons, but because people complained that the large process IDs looked ugly in Task Manager. (One customer even asked if something was wrong with his computer.)"

Processes, commit, RAM, threads, and how high can you go?


PID是一個什麼東西?

它是一個表的索引項,這個表是PspCidTable,保存了所有進程信息(貌似還有別的東西),ProcessID是這個表的索引(索引值*4),創建、查找、刪除進程的時候實際上都在訪問PspCidTable這個表。

手頭沒有最新的Windows代碼,所以無法判斷ProcessID的最新定義。

從過去的代碼上看,它的定義範圍是32位整形(DWORD),從代碼邏輯上看,它是PspCidTable索引的值左移2位獲得。

整個PspCidTable是一個三級索引的結構,每級256個,所以索引最大值應該是16777216,ProcessID最大值是16777216*4 = 67108864。

所以我認為 @Zyzsdy Ted 的結論可能是不正確的,至少目前為止不是這樣的,不會有超過2^26的數字出現。

如果為了安全起見,代碼中定義ProcessID應該是DWORD。但微軟沒有專門定義ProcessID這個數據類型,內核中也有大量使用Handle作為ProcessID的類型,所以誰知道將來會是什麼樣呢……

貼一點點代碼,如果有侵權問題我會刪除:

l = (Handle.Index &>&> 24) 255;
i = (Handle.Index &>&> 16) 255;
j = (Handle.Index &>&> 8) 255;
k = (Handle.Index) 255;

if ( l != 0 ) {
return NULL;
}
if (HandleTable-&>Table[i] == NULL) {
return NULL;
}
if (HandleTable-&>Table[i][j] == NULL) {
return NULL;
}
return (HandleTable-&>Table[i][j][k]);

EXHANDLE的定義如下:

typedef struct _EXHANDLE {
union {
struct {
ULONG TagBits : 2;
ULONG Index : 30;
};
HANDLE GenericHandleOverlay;
};
} EXHANDLE, *PEXHANDLE;

最低2位是tag,所以PID都是4的倍數。

最後貼的圖:


先說結論:

4~4294967292

===============================================

我一般不關電腦,也不重啟。大概連續用了一個多月。

有天我重啟apache進程。重啟過後我看了一眼pid

712292

七十多萬的pid。。。。。。。(我當時就截圖上傳發朋友圈了)

題主才見到一個十萬的pid就大驚小怪什麼。

pid是DWORD的(WinApi返回pid的地方類型都是DWORD),所以上限應該是DWORD的上限。

做Windows編程的話,把Windows.h導入進來然後直接用DWORD類型就好了。如果不是C++,win內部的各種handle最好都用uint存。

==============================================

我見過太多用ushort存pid最後崩了的問題了。很多人連五位數pid都沒見過,想當然的認為pid是個ushort了。

還有就是linux編程做多了。。認為32768是pid上限天經地義。上次有個人還跟我爭半天,然後我拿出了我那張祖傳的七十萬pid的截圖。

估計很多人都沒想過Windows的PID能取到四十多億。

pid是這樣定義的:前30位是順序號,後2位是標誌位。

創建進程時,標誌位取00,所以所有的pid都應該是4的倍數。

這樣最小的pid就應該是0x4(二進位100)

最大的pid就應該是0xFFFFFFFC(二進位三十個1,後面兩個0)

=====================9.27更新===========

抱歉昨天太忙了沒時間找。。剛才找到圖了。。補上圖。。。


偏個題,我也晒晒PID(逃

PID 14246768 一千多萬的PID

開機14個月


GetProcessId返回的是DWORD,120000不會溢出。至於你為什麼要假設pid是個小於DWORD範圍的值,這才是該自我批評的地方。


感覺是越分配越大的。如果你幾個星期不重啟電腦,不斷的開程序、關程序,應該可以等到PID的上限。話說你可以不用uint,但至少要用個int來存PID嘛,用了short類型來存,溢出那不是輕輕鬆鬆~~

附一個剛剛查到的帖子~ winapi - What is the maximum process Id on Windows?


以前在做隱藏進程檢測的時候,有一種RING3下常用的方案就是枚舉所有的PID,以4為步進值一個個嘗試OpenProcess. 同時可以在每個ID上加上1-3的偏移,這樣就可以檢測到斷ActiveProcessList鏈的進程,同時BYPASS那些只過濾PID嚴格相等的鉤子。

當時我以為PID值不會超過10000(因為沒見過),就用了張10000/4大小的數組做HASH。。。


作為一名自動化狗,我以為題主說的PID是PID控制………


http://blogs.msdn.com/b/oldnewthing/archive/2011/01/06/10112270.aspx

算是官方回答了


DWORD正數範圍都是合法範圍。pid是個遞增值。出現那麼大的值可能是不斷有進城起來又退出。


請問,Linux進程PID最大是多大呢?


斷的開程序、關程序,應該可以等到PID的上限。


推薦閱讀:

為什麼微軟不對桌面軟體制定嚴格性能要求?
lumia950xl實際使用體驗如何?
Windows Phone 到底爽在哪裡?
為什麼 MacType 這種「邪魔歪道」的軟體會出現併流行?
Windows 系統為什麼對高分屏支持不好?

TAG:MicrosoftWindows | 編程 | WindowsXP | 進程 |