Microsoft MVP성태의 닷넷 이야기
.NET Framework: 2094. C# - Job에 Process 포함하는 방법 [링크 복사], [링크+제목 복사],
조회: 12715
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일

C# - Job에 Process 포함하는 방법

개인적으로 단 한 번도 Job을 생성한 프로젝트를 해 본 적이 없는데요, 아마도 마이크로소프트 이외에는 거의 안 쓰는 커널 자원이지 않을까... 싶습니다. ^^ (혹시, 사용하고 계신 분 있으시면 어떤 상황에서 쓰시고 계신지 덧글 부탁드립니다.)

마침 oldnewthing 블로그에 Job과 관련한 글이 올라왔는데요,

A more direct and mistake-free way of creating a process in a job object
; https://devblogs.microsoft.com/oldnewthing/20230209-00/?p=107812

Windows 10/Windows Server 2016 미만의 운영체제에서는 Job에 프로세스를 할당하는 과정이 이렇게 된다고 합니다.

  1. 프로세스를 suspend 상태로 생성
  2. Assign­Process­To­Job­Object API를 사용해 Job에 프로세스 연결
  3. 중지시켰던 프로세스를 resume

문제는, 1번 과정을 수행 후 2번 과정으로 넘어가는 중에 현재의 프로세스가 종료해 버리면 suspend 상태로 실행해 두었던 프로세스가 붕 떠버리는(orphaning the process) 결과가 발생한다는 겁니다.

이런 문제를 해결하기 위해 "PROC_THREAD_ATTRIBUTE_JOB_LIST" 옵션이 추가되었고, 이를 활용하면 프로세스를 생성하는 시점에 Job에 할당하는 것이 가능합니다. 본문에서는 그에 대한 C/C++ 코드가 실려 있는데요, C#으로는 다음과 같이 변경할 수 있습니다.

// ...[생략: 전체 소스 코드는 첨부 파일을 확인하세요.]...

static void Main(string[] args)
{
    IntPtr job = CreateJobObject(IntPtr.Zero, null);

    nint size = 0;
    InitializeProcThreadAttributeList(IntPtr.Zero, 1, 0, ref size);
    nint p = Marshal.AllocHGlobal(size);

    InitializeProcThreadAttributeList(p, 1, 0, ref size);

    nuint flags = ProcThreadAttributeValue(ProcThreadAttributeJobList, false, true, false);
    bool result = UpdateProcThreadAttribute(p, 0, flags, ref job, IntPtr.Size, IntPtr.Zero, IntPtr.Zero);

    string cmd = "C:\\Windows\\System32\\cmd.exe";
    STARTUPINFOEX siex = new STARTUPINFOEX();
    siex.lpAttributeList = p;
    siex.StartupInfo.cb = Marshal.SizeOf<STARTUPINFOEX>();
    PROCESS_INFORMATION pi;

    CreateProcess(cmd, cmd, IntPtr.Zero, IntPtr.Zero, false, CREATE_NEW_CONSOLE | EXTENDED_STARTUPINFO_PRESENT,
        IntPtr.Zero, null, ref siex, out pi);

    bool isInJob;
    IsProcessInJob(pi.hProcess, job, out isInJob);
    Console.WriteLine($"In job: {isInJob}");

    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

    Marshal.FreeHGlobal(p);

    CloseHandle(job);
}

Job과 관련한 기능은 닷넷 런타임의 범위에는 속하지 않으므로 모든 API를 P/Invoke로 연결해 호출해야 합니다. 또한, C#의 ProcessStartInfo는 lpAttributeList를 설정할 수 있는 옵션을 제공하지 않아 STARTUPINFOEX/CreateProcess까지도 모두 P/Invoke로 호출해야 하고!

어쨌든 저 코드를 실행하면 화면에는 "In job: True"라는 문자열이 출력되고, Visual Studio에서 그 라인에 BP로 멈춰 Process Explorer를 통해 확인해 보면 cmd.exe 프로세스가 Job에 속해 있는 것을 볼 수 있습니다.

cs_createjob_1.png

(첨부 파일은 이 글의 예제 코드를 포함합니다.)





[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]







[최초 등록일: ]
[최종 수정일: 2/13/2023]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 



2023-03-23 07시53분
Why does the usage of the initial registers of a Win32 process depend on whether it is a 32-bit or 64-bit process?
; https://devblogs.microsoft.com/oldnewthing/20230321-00/?p=107954
정성태

... 181  182  183  184  185  186  187  188  189  190  [191]  192  193  194  195  ...
NoWriterDateCnt.TitleFile(s)
169정성태10/14/200520798    답변글 VS.NET IDE: 33.1. Enable rapid-fail protection 상황 재현 방법
166정성태11/14/200518020.NET Framework: 48. IE를 죽이는 스크립트 소스
165정성태11/14/200518650.NET Framework: 47. MOM (Microsoft Operations Manager) 2005 서버 설치 가이드
164정성태11/14/200515921.NET Framework: 46. 도메인에 속한 컴퓨터의 Local Computer Policy 변경 방법
162정성태10/3/200518613.NET Framework: 45. VS.NET 2005 IDE에서 Web App를 .NET 2.0 (x64) 머신에 배포
161정성태11/14/200521482.NET Framework: 44. IIS 관리자에서 ASP.NET 탭이 없는 경우.
159정성태9/28/200517421VS.NET IDE: 32. Virtual Server 2005 64bit SP1 Beta 테스트 [2]
163정성태10/3/200515498    답변글 VS.NET IDE: 32.1. 왜...?
158정성태11/14/200517937VS.NET IDE: 31. SQL 2005 - A connection was successfully established with the server
157정성태9/21/200517717기타: 10. SQL2000 설치 시, Invalid Product Key 오류
156정성태9/16/200519662.NET Framework: 43. Wisptis.exe 프로세스
155정성태5/31/200516027.NET Framework: 42. .NET Installer Class에서 Install 메서드 - 설정 사항들 알아내는 코드
154정성태5/13/200514962VS.NET IDE: 30. Windows 2003 for x64에 추가된 레지스트리 Run 노드
152정성태5/5/200518398VC++: 18. VC++ 7.0에서부터 ? : 연산자 처리가 바뀌었습니다.
153정성태5/12/200518533    답변글 VC++: 18.1. VC++ 8.0에서부터 바뀐 CRT 소개
151정성태5/5/200521478VC++: 17. DLL에 export 된 C++ 클래스 멤버 함수 파라미터형 정보 알아내는 방법
150정성태5/5/200522707.NET Framework: 41. 태그 사이의 값을 추출하는 정규식
149정성태5/5/200519132.NET Framework: 40. 데이터그리드에서 콤보박스 쓸 수 있는 방법
148정성태5/5/200519703.NET Framework: 39. DataSet 방식을 RecordSet으로 구현하는 방법.
147정성태5/7/200617247VC++: 16. 클래스 멤버 함수에 대한 포인터를 받는 표현.
146정성태4/29/200516225VS.NET IDE: 29. 네트워크 공유를 다른 사용자 계정으로 다시 로그인을 원하는 경우.
144정성태4/14/200516678VS.NET IDE: 28. Windows 2003 SP1을 설치하고.
143정성태5/5/200517843.NET Framework: 38. DSL (Domain Specific Language)
141정성태4/14/200518787VS.NET IDE: 27. 64bit 컴퓨터 사용 평가 [3]
140정성태4/14/200515868.NET Framework: 37. String.GetHashCode의 리턴값. 그때그때 다릅니다.
138정성태4/12/200516724.NET Framework: 36. 64bit 시스템 구성
... 181  182  183  184  185  186  187  188  189  190  [191]  192  193  194  195  ...