출처 : 열혈 TCP/IP 소켓 프로그래밍 윤성우 저
커널 오브젝트란?
윈도우 운영체제가 생성해서 관리하는 모든 리소스
파일 데이터의 입출력, 스레드, 프로세스등 윈도우에서 운영체제가 관리하기 위해 리소스 정보를 위한 데이터 블록을 생성하고 관리하도록 한다. 이러한 데이터 블록을 '커널 오브젝트'라하며 리소스마다 관리되는 정보량이 다르기 때문에 데이터 블록의 크기도 각각 다르다.
커널 오브젝트의 소유자는 운영체제이며, 생성, 관리 그리고 소멸시점까지 결정하는 것은 모두 운영체제의 몫이다.
윈도우기반의 스레드 생성
main 함수가 프로그램의 시작이 되는 프로그램에서 main 함수를 호출하는 주체는 스레드이다. 예전 운영체제 시스템에서는 프로세스가 실행 흐름의 최소 단위였던 적이 있었으나 현대 운영체제에서는 스레드가 기본 단위가 되는 프로그램을 지원한다. 이에 "단일 스레드 프로그램" 은 main 함수 이외에 별도의 스레드를 생성하지 않는 프로그램이며 "멀티 스레드 프로그램"은 스레드를 별도로 생성하는 방식이다.
C 프로그램에서 스레드 생성
#include <process.h>
uintptr_t _beginthreadex(void* security, unsigned stack_size, unsigned (*start_adress)(void*),
void* arglist, unsigned initflag, unsigend *thrdaddr);
반환되는 uintptr_t는 HANDLE형 자료형과 같고 이 커널 오브젝트를 다룰 수 있는 디스크립터 역할을 한다. 핸들 값은 프로세스에서는 고유하지만 다른 프로세스에서 중복된 값이 있을 수 있다. thrdaddr에 넘겨주는 주소값에 고유 스레드 ID가 저장되며 이는 프로세스에 상관없이 고유한 값을 가진다.
커널 오브젝트의 상태
커널 오브젝트는 초기화시 non-signaled 상태로 초기화 되며 종료시 signaled 상태가 된다. signaled 상태는 이벤트가 발생한 상태를 의미하며 해당 리소스가 특정상황에 도달한 것을 의미한다. 이러한 상태 값은 boolean 변수로 true/false 값을 저장하여 내부 데이터 블록에 가지고 있다.
상태를 확인하는 함수
- 하나의 커널 오브젝트에 대해
#include <windows.h>
DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds);
- hHandle: 상태 확인 대상의 커널 오브젝트 핸들
- dwMilliseconds: 1/1000초 단위로 타임아웃을 지정, INFINITE 전달시 무한 대기.
- 반환 값: signaled 상태로는 WAIT_OBJECT_0 혹은 타임아웃으로 반환 시 WAIT_TIMEOUT 반환
"auto-reset" 모드 커널 오브젝트: 이벤트 발생에 의하여 signaled 상태가 반환되었을 때, 해당 커널 오브젝트의 상태가 non-signaled 상태로 돌아가는 커널 오브젝트를 말한다.
"manual-reset" 모드 커널 오브젝트: 반대로 signaled 상태가 반환되었음에도 해당 커널 오브젝트 상태가 non-signaled 상태로 돌아가지 않는 커널 오브젝트를 말한다.
WaitForSingleObject는 전달된 핸들의 커널 오브젝트가 signal 상태가 되어야만 함수가 반환한다.
- 다수의 커널 오브젝트에 대해
DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAll, DWORD dwMilliseconds);
- nCount: 검사할 커널 오브젝트 수
- lpHandles: 핸들정보를 담고 있는 배열 주소
- bWaitAll: 모든 검사 대상이 signaled 상태 일때만 반환 (TRUE), 하나라도 signale 상태가 되면 반환 (FALSE)
- dwMilliseconds: 1/1000초 단위로 타임아웃 지정. INFINITE 전달시 무한 대기.
다수의 커널 오브젝트에 대하여 signal 상태가 되었을 때 함수가 반환한다.
윈도우 기반 스레드 생성 예제
#include <stdio.h>
#include <windows.h>
#include <process.h>
unsigned WINAPI ThreadFunc(void* arg);
int main(int argc, char* argv[])
{
HANDLE hThread;
DWORD wr;
unsigned threadID;
int param = 5;
hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadFunc, (void*)¶m, 0, &threadID);
if (hThread == 0)
{
puts("_beginthreadex() error");
return -1;
}
if((wr=WaitForSingleObject(hThread, INFINITE)) == WAIT_FAILED)
{
puts("thread wait error");
return -1;
}
printf("wait result: %s \n", (wr == WAIT_OBJECT_0) ? "signaled" : "time-out");
puts("end of main");
return 0;
}
unsigned WINAPI ThreadFunc(void* arg)
{
int i;
int cnt = *((int*)arg);
for (i = 0; i < cnt; ++i)
{
Sleep(1000);
puts("running thread");
}
return 0;
}
'Computer Science 기본 지식 > 소켓 프로그래밍' 카테고리의 다른 글
[TCP/IP 소켓 프로그래밍] (15) 비동기 모델 Asynchronous Notification IO (0) | 2021.04.07 |
---|---|
[TCP/IP 소켓 프로그래밍] (14) 쓰레드 동기화 (윈도우) (0) | 2021.04.06 |
[TCP/IP 소켓 프로그래밍] (12) 다중 접속 서버 - 쓰레드 (0) | 2021.04.06 |
[TCP/IP 소켓 프로그래밍] (11-2) 다중 접속 서버 - 레벨 트리거/엣지 트리거 (0) | 2021.04.05 |
[TCP/IP 소켓 프로그래밍] (11-1) 다중 접속 서버 - epoll (0) | 2021.04.05 |