반응형

06.7z
0.07MB

 

 

다수의 객체가 공유 자원에 접근하려고 하면, 접근 시점을 동기화 해줘야 한다.

 

멀티 Thread 프로그램도 공유 자원에 여러 개의 쓰레드가 접근할 수 있으므로 공유 자원 영역에 대한 동기화가 필요하다.

 

일반적으로 동기화는 공간과 시간을 제어하는 방식으로 이루어지는데, 즉, 접근 제어가 필요한 공간을 지정하고 지정한 공간에 진입할 수 있는 시간을 제어하는 방식이다.

 

화장실과 화장실 열쇠가 하나만 있고, A 와 B라는 사람이 있을 때 A라는 사람이 먼저 열쇠를 이용해 화장실을 사용 중이라면 B는 기다려야 한다.

 

A가 화장실을 다 쓰고 열쇠를 되돌려놓으면 그제서야 B가 사용할 수 있는데 B가 사용 중일 때는 A가 또 화장실을 가고 싶어도 기다려야 한다.

 

이때 화장실을 임계 영역이라고 말하고, 화장실 열쇠를 mutex라고 말한다.

 

mutex(Mutual Exclusion : 상호 배제)는 pthread에서 제공하는 동기화 매커니즘인데, 공유 자원 공간(임계 영역)에 대한 접근 시간 제어로 동기화를 달성한다.

(A가 사용 중일 때 화장실 문을 잠궈서(쓰레드를 잠궈서) 다른 사람이 들어올 수 없도록 하기 때문에 B는 대기, B가 사용 중일 때는 A가 대기)

 

기본적인 매커니즘은 세마포어와 비슷하고, POSIX 세마포어와 더 비슷하며, 동기화 매커니즘으로 mutex 대신 세마포어를 사용할 수도 있다고 한다.

 

하지만 위의 내용은 어디까지나 매커니즘 상으로의 얘기이고, 세마포어처럼 busy wait 상태에 놓이지 않음을 보장한다.

 

즉, 정리하면 Mutex는 여러 스레드에서 하나의 임계 영역에 접근할 때 생기는 동기화 문제를 해결하기 위한 매커니즘으로, A 스레드가 임계 영역을 사용 중일 때는 스레드를 잠궈 다른 스레드가 접근 할 수 없도록 하고, 다른 스레드는 잠금이 풀릴 때까지 기다리게 만드는 기능이다.

 

이 문제에서 Thread Mutex는 무엇인가 라는 말은 문제 파일의 흐름에서 여러 스레드가 한 공유 자원을 접근하는 부분이 있을 것이고, 그 부분을 제어하는 Thread Mutex의 이름이나 주소가 무엇인지를 물어보는 것이다.

 

 

 


분석

 

 

위의 흐름도를 보면 CreateMutexA() 함수가 보인다.

 

이 함수가 뮤텍스를 생성하거나 여는 함수이다.

 

HANDLE CreateMutexA(
  [in, optional] LPSECURITY_ATTRIBUTES lpMutexAttributes,
  [in]           BOOL                  bInitialOwner,
  [in, optional] LPCSTR                lpName
);

/*
lpMutexAttributes - SECURITY_ATTRIBUTES 구조체에 대한 포인터입니다. 이 매개 변수가 NULL이면 자식 프로세스에서 핸들을 상속할 수 없다

bInitialOwner
- 이 값이 TRUE 이고 호출자가 뮤텍스를 만든 경우 호출 스레드는 뮤텍스 개체의 초기 소유권을 얻는다.
- 소유권을 얻는다는 것은 Mutex를 가지고 있을 경우 해당 쓰레드가 실행된다는 뜻이다.

lpName
- 뮤텍스 개체의 이름이다.
- 이름은 MAX_PATH 문자로 제한된다.
- 이름 비교는 대/소문자를 구분한다.
*/

 

CreateMutex 함수의 정의와 매개변수를 보면 위와 같다.

 

 

Start 부분을 보면 위와 같은데

 

이름은 bagla_super_downloader_1000이고, bInitialOwner이 1로 설정되어 있으며, lpMutexAttributes는 0으로 설정된 뮤텍스를 생성한다.

 

그리고 GetLastError 함수를 호출하는데 반환값이 0B7h라면, 즉 mutex가 성공적으로 생성되지 않으면 false 쪽 4018BA 주소로 간 후 4019A3 주소로 이동하여 프로그램을 종료한다.

 

성공적으로 mutex가 생성되면 4018D5 주소로 가고, 4017DA 주소의 함수를 호출 한 뒤

SetErrorMode, GetModuleHandleA, GetProcAddress 함수를 호출하고 성공적으로 함수들이 호출됐다면 바로 401911 주소로 가고

성공적으로 함수들이 호출되지 않으면 4022B8 주소의 함수를 호출하고 401911 주소로 간다.

 

 

401911 주소를 보면 CreateThread 함수를 호출하고 CreateMutexA 함수를 호출한다.

 

그리고 4013A1 주소의 함수를 호출 후 29Ah 값과 같으면 401950 주소로 가고 401966 주소로 가서 96000밀리세컨드 동안멈춘 후 다시 401950 주소로 가는 반복문을 돈다.

 

같지 않으면 401973 주소로 가고  ReleaseMutex 함수 -> CloseHandle 함수 -> sleep 함수 -> ExitProcess 함수 호출 후 4019A3 주소로 가서 종료한다.

 

// https://learn.microsoft.com/ko-kr/windows/win32/api/processthreadsapi/nf-processthreadsapi-createthread

HANDLE CreateThread(
  [in, optional]  LPSECURITY_ATTRIBUTES   lpThreadAttributes,
  [in]            SIZE_T                  dwStackSize,
  [in]            LPTHREAD_START_ROUTINE  lpStartAddress,
  [in, optional]  __drv_aliasesMem LPVOID lpParameter,
  [in]            DWORD                   dwCreationFlags,
  [out, optional] LPDWORD                 lpThreadId
);

 

CreateThread 함수의 정의를 보면 위와 같다.

 

매개변수 중 lpStartAddress 매개변수는 스레드에서 실행할 애플리케이션 정의 함수에 대한 포인터로, 이 포인터는 스레드의 시작 주소를 나타낸다.

 

아마 lpStartAddress 매개 변수 부분에 있는 값 40174C 주소의 스레드가 임계영역이지 않을까 싶다.

(해당 주소의 스레드가 임계 영역이 아니라면 댓글 부탁드립니다 :D)

 


풀이

 

총 2번의 CreateMutexA 함수가 호출되는데 첫 번째 CreateMutexA 함수는 호출 이전에 Thread를 생성하는 것이 없으므로 소유자가 없는 채로 생성되는 것이다.

 

그리고 두 번째 CreateMutexA 함수는 호출 이전에 Thread를 생성하는 것이 있으므로 Thread를 제어하는 Thread Mutex이고, 이 Mutex의 이름은 smtp_bagla_1000이니 답은 smtp_bagla_1000이다.

반응형

+ Recent posts