none
OpenProcessにおける the Idle process について RRS feed

  • 質問

  • https://msdn.microsoft.com/en-us/library/windows/desktop/ms684320(v=vs.85).aspx

    こちらを参照すると、dwProcessId について以下のように説明があります。

    If the specified process is the Idle process or one of the CSRSS processes, this function fails and the last error code is ERROR_ACCESS_DENIED

    ここでいう"the Idle process"とは何を指すのでしょうか?

    System Idle Process は System Process (0x00000000) のことだと思いますので、the Idle process とは違うという認識です。

    質問の意図としては、任意のタイミングで起動中のプロセスが何かを取得したいのですが

    開けない仕様のものをエラーログに出したくないので区別したいためです。

    2017年6月5日 3:24

回答

すべての返信

  • Idle process (process ID 0)

    ...

    System process (process ID 4)

    "System Processes", Windows Internals, Sixth Edition, Part 1

    2017年6月5日 4:44
  • リンク先のドキュメントは

    If the specified process is the System Process (0x00000000), the function fails and the last error code is ERROR_INVALID_PARAMETER. If the specified process is the Idle process or one of the CSRSS processes, this function fails and the last error code is ERROR_ACCESS_DENIED because their access restrictions prevent user-level code from opening them.

    とあり、ここに書かれている0x00000000がドキュメントバグで、正しくはHomeClosetさんの記述の通りですね。

    2017年6月5日 4:59
  • デバッガでは以下のように出るので、0x00000000 についてはドキュメント バグとも言えないかと。

    2: kd> .tlist
        0n0 System Process
        0n4 System


    • 編集済み HomeCloset 2017年6月5日 5:30 言葉追加
    2017年6月5日 5:17
  • int _tmain(int argc, _TCHAR* argv[])
    {
    	TCHAR out[1024] = {0};
    	TCHAR path[MAX_PATH] = {0};
    
    	HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    
    	if(hSnapshot)
    	{
    		PROCESSENTRY32 pe32;
    		pe32.dwSize = sizeof(PROCESSENTRY32);
    
    		if(Process32First(hSnapshot, &pe32))
    		{
    			do
    			{
    				HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pe32.th32ProcessID);
    
    				if(!hProcess)
    				{
    					sprintf(out, "PID[%d]  PATH[%s] CODE[0x%X]\r\n", pe32.th32ProcessID, pe32.szExeFile, GetLastError());
    					cout << out;
    				}
    			}
    			while(Process32Next(hSnapshot, &pe32));
    		}
    	}
    	Sleep(60000);
    	return 0;
    }

    このような感じで出力してみています。

    結果(抜粋)

    PID[0]  PATH[[System Process]] CODE[0x57]
    PID[4]  PATH[System] CODE[0x5]
    PID[264]  PATH[smss.exe] CODE[0x5]
    PID[344]  PATH[csrss.exe] CODE[0x5]
    PID[396]  PATH[csrss.exe] CODE[0x5]
    PID[404]  PATH[wininit.exe] CODE[0x5]
    PID[432]  PATH[winlogon.exe] CODE[0x5]
    PID[504]  PATH[services.exe] CODE[0x5]
    PID[516]  PATH[lsass.exe] CODE[0x5]

    この結果を見ると、SystemIdleProcessについての解釈は間違っていないのかと考えています。

    > System Idle Process は System Process (0x00000000) のことだと思いますので

    GetLastErrorで0x5となるものがすべて"the Idle process"にあたるのでしょうか?

    【追記】

    PID=0がタスクマネージャで見るとプロセス名に"System Idle Process"となっているのは気づいていました。

    スナップショットを参照した際に"[System Process]"となっていたため、Idleとは?というところで質問に至っています。

    【再追記】

    System以外の0x5は管理者権限であれば開けるものでした。(なぜかCSRSSもOpenProcessできていそうでした)

    あと適当に作ったとはいえハンドルのクローズをしていなかったですね。

    • 編集済み Masashi.O 2017年6月5日 6:20
    2017年6月5日 5:26
  • OpenProcess() のドキュメントの "the Idle process" が、"the System process (0x4)" の書き間違いなのではないでしょうか。
    2017年6月5日 5:55
  • つまりドキュメントバグですかね?
    2017年6月5日 6:06
  • 確かにSystem processと書かれていれば辻褄が合っていると思います。

    2017年6月5日 6:15
  • "System Process" と "System Idle Process" の違いは、"Windows Internals" に説明があります。
    -------------------------------------------------
    Windows Internals, Sixth Edition, Part 1 eBook
    http://materias.fi.uba.ar/7508/WI6/Windows%20Internals%20Part%201%20(6th%20Edition).pdf

    p.68    "System Processes"
    p.69    "System Idle Process"
    p.453   "Idle Threads"
    -------------------------------------------------

    "System Process" と "System Idle Process" は特殊なプロセスです。
    サービス プロセスやアプリケーション プロセスは、必ずユーザー モード空間とカーネル モード空間で構成されますが、"System Process" と "System Idle Process" はユーザー モード空間を持ちません。
    なので、OpenProcess() API 等のユーザー モード空間側からのアクセスは、不可となります。

    "System Idle Process" は "Idle Thread" で構成され、"Idle Thread" は各 CPU 毎に一つづつ生成されます。
    そして生成された "Idle Thread" は、実行可能なスレッドが CPU 上に存在しない場合にのみ、実行されます。
    "System Process" と "System Idle Process" は、カーネル モード空間のみで構成される特殊なプロセスという共通点を持ちますが、プロセス オブジェクト (EPROCESS 構造体) としては完全に分離しているので別モノになります。
    ただし依存関係はあります。
    "System Idle Process" の状態を WinDBG から確認すると、"System Idle Process" に対して "System Process" は "Attached Process" として表示されるので、"System Process" は "System Idle Process" の親プロセスなのかもしれませんが、それを断言できるだけの確証を私は持ち合わせていません。

    "System Process" と "System Idle Process" の PID は、大昔から "System Process" が 4 で "System Idle Process" が 0 で固定のようです。
    (ただし、今後もそれが保証されるかどうかは知りません。)

    ちなみに、プロセス オブジェクトの自体である EPROCESS 構造体の "ImageFileName" メンバーには、 "System Process" が "System"、 "System Idle Process" が "Idle" がそれぞれセットされるようです。

    2017年6月5日 8:26
  • > "System Process" と "System Idle Process" はユーザー モード空間を持ちません。
    > なので、OpenProcess() API 等のユーザー モード空間側からのアクセスは、不可となります。

    勉強になりました。ありがとうございます。

    >"System Process" と "System Idle Process" の PID は、大昔から "System Process" が 4 で "System Idle Process" が 0 で固定のようです。
    >(ただし、今後もそれが保証されるかどうかは知りません。)

    Windows10が最後のWindowsになるという話をどこかでみましたので、現状でPID0と4を判定するのは問題なさそうですね。

    変わったらその時に考える方針にしました。
    • 編集済み Masashi.O 2017年6月6日 2:35
    2017年6月6日 1:16
  • 返信をくださった皆様、ありがとうございました。

    結局"the Idle process"が何を指すかはわかりませんでしたが、目的を果たすために何をすれば良いかはわかりましたので

    最初にいただいたHomeClosetさんの返信を回答としてマークしました。

    2017年6月6日 1:20