1

プロセスを使用すると、次のことができます。

int pid;
::CreateProcess(NULL, cmd, ..., &pi);
pid = pi.dwProcessId;
::CloseHandle(pi.hProcess);
// then later...
HANDLE proc = ::OpenProcess(PROCESS_TERMINATE, FALSE, pid);
::TerminateProcess(proc, 1);
::CloseHandle(proc);

このように、Windows プロセスを pid のみで管理できます。これは、マルチプラットフォーム コードに適しています。

このパターンをジョブ オブジェクトに拡張したいと思います。

HANDLE job = ::CreateJobObject(NULL, name);
::AssignProcessToJobObject(job, proc); // proc from above
::CloseHandle(job);
// then later...
job = ::OpenJobObject(JOB_OBJECT_TERMINATE, FALSE, name);
::TerminateJobObject(job, 1);

明確にするために、私は仕事をしていませんが、私の子プロセスは仕事をしています。MSDN は、「最後のハンドルが閉じられ、関連するすべてのプロセスが終了すると、ジョブは破棄されます」と述べています。この場合、私のメイン プロセスは最後のハンドルを閉じましたが、子プロセスはまだ実行中であり、まだハンドルを持っています。IsProcessInJob(proc, NULL, &isit)ジョブがまだ存在することを確認する呼び出し。ただし、ジョブを開く呼び出しは NULL を返し、エラー コードは ERROR_FILE_NOT_FOUND です。

質問: 私のメイン プロセスには、ジョブを閉じた後にジョブを処理する方法はありますか?

4

2 に答える 2

2

これが NT オブジェクト マネージャの仕組みです。ほとんどすべてのオブジェクトは "一時的" です。つまり、オブジェクトへの参照 (カーネル モードのポインター参照またはハンドル) が存在しなくなると、オブジェクトは削除されます。NtMakePermanentObjectジョブ オブジェクトを呼び出して、この動作を変更できるはずです。私はこれまでにこれを試したことはありません。

于 2012-12-19T10:25:57.870 に答える
2

Yes, it is possible. However, observe:

// This example will fail to reopen and terminate the job.
// Processes cmd and ping stay running
STARTUPINFO si;
memset(&si, 0, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
PROCESS_INFORMATION pi;
memset(&pi, 0, sizeof(PROCESS_INFORMATION));

// BEGIN BLOCK A
::CreateProcess(NULL, "cmd /c ping 127.0.0.1 -n 10 > nul",
    NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, ".", &si, &pi);
HANDLE job = ::CeateJobObject(NULL, "myjob");
::AssignProcessToJobObject(job, pi.hProcess);
// END BLOCK A

::ResumeThread(pi.hThread);
::CloseHandle(pi.hProcess);
::CloseHandle(pi.hThread);
::CloseHandle(job);
HANDLE reopenJob = ::OpenJobObject(JOB_OBJECT_TERMINATE, FALSE, "myjob");
if(reopenJob != NULL)
    ::TerminateJobObject(reopenJob, 1);

The reopened job in this case is NULL, and the error code is ERROR_FILE_NOT_FOUND.

The job must be created before the process, and be inherited, for the job to be reopenable.

// NEW BLOCK A
HANDLE job = ::CreateJobObject(NULL, "myjob");
::SetHandleInformation(job, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
::CreateProcess(NULL, "cmd /c ping 127.0.0.1 -n 10 > nul",
    NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, ".", &si, &pi);
::AssignProcessToJobObject(job, pi.hProcess);

If your goal is to name the job using the PID, note that this creation order prevents such a convention. This still means that some piece of information must be tracked in addition to the PID in order to reopen the job.

于 2012-12-21T22:43:03.730 に答える