10.9(화) 이론-2( 스레드 )

from Study/System 2007/10/14 15:58 view 19927
1. 스레드!!!

  - 개념 ( 윈도우는 스레드기반으로 돌아간다. )
    1) 가상주소 => 페이지테이블 => 물리주소
    2) CR3 : 페이지 테이블의 주소
    3) CPU는 10ms씩 인터럽트가 발생하여 Context Switching 이 발생
    4) 인터럽트 Handler 는 스케줄러 담당한다. 두개이상의 프로세스가 동시에 실행되도록 한다.
    5) 퀀텀Time : 20ms 최소의 실행시간을 보장해준다.
    6) 메시지Q는 GUI 요소를 갖는 윈도우만 가지고 있다.
    7) GetMessage() 에서 message가 없다면 Context Switching 이 발생..
    8) Sleep(0); 을 해서 강제로 C.W 발생..
    9) 메모리 관리 : 프로세스가 CR3를 가지고 있다.(ReadProcessMemory는 CR3의 주소값을 참조.)
   10) 실행흐름 : 스레드가 관리한다.

  - 함수
    1) CreateThread, CreateRemoteThread ( 다른프로세스에 스레드를 생성 ), _beginThreadex

  - 주스레드에서(main()) 스레드A를 생성하게 되면 ETHREAD에 1MB의 스택영역이 생성된다.
  - 주스레에서 main리턴하게 되면 프로세스가 종료되고, ExitThread를 해주면 주스레드만 종료된다.
  - 다른 스레드의 종료를 대기해줘야 할때 ( WaitForxxx )
    1) WaitForSingleObject - 스레드구조체의 staterk signal 상태가 되기를 기다리게 된다.

  - WaitForSingleObject 의 원리
    1) dt nt!_KEVENT, dt nt!_KTHREAD 에는 공통적으로 _DISPATCHER_HEADER 가 있다.
+0x000 Header           : _DISPATCHER_HEADER
///////////////////////////////////////////////////////////////////////////////////////
   +0x000 Type             : UChar
   +0x001 Absolute         : UChar
   +0x002 Size             : UChar
   +0x003 Inserted         : UChar
   +0x004 SignalState      : Int4B  <= 모든 KO는 이를 가지고 있다. 실행과 대기를 위해서~~
   +0x008 WaitListHead     : _LIST_ENTRY

2. MulitiThread
DWORD CALLBACK foo( void* p )
{
    int x;                // TLS 내에 생긴다.(Thread Local Storage) 지역변수는 Thread Safe 
    static int y;       // 프로세스의 static 공간에 생긴다. 스레드에 안전하지 않다. CriticalSection

    return 0;
}

- CriticalSection 영역을 ThreadSafe 하기 위해선 CRITICAL_SECTION을 사용한다.
- Serializetion( 직렬화 ) : 2차선 -> 1차선으로 바꿔서 스레드 한개만 활동하게 한다.

- 듀얼 코어에서는 자러가는시간 1000ms 과 깨어나는 시간 100ms 라면 깨어나는 Thread가 계속 실행될 수 있다. 그래서 SpinCounter 500ms 정도로 설정하여 CS에 진입을 재시도 하게 한다.

3. 원자 연산 ( Atomic Operation )
DWORD CALLBACK foo( void* p )
{
    for ( int i = 0; i < 10000; ++i )
    {
        // COM 기반 기술에서 자주 사용한다.!!!!!!!
 
      InterlockedExchange( &x, 0 ); // x = 0
        InterlockedExchangeAdd( &x, 5 );    // x = x+5;
        InterlockedDecrement( &x ); // x -= 1;
        InterlockedIncrement( &x );    // lock inc x 로 구현된 함수. x += 1

        x = x+1;    // 보장받지 못한다.

        __asm
        {
            lock inc x // inc 는 원자 연산이다. 즉, inc 실행중 절대 Context Switch가 발생안함.


           // 아래 명령어는 원자 연산을 보장 하지 못한다.

            mov eax,    x
            add eax,    1
            mov x,        eax
          ///////////////////////////////////////////////
        }
    }
    return 0;
}

  - asm으로 원잔연산을 보장 해주기 위해선 inc 라는 명령어를 사용한다.
  - 듀얼코어에서는 lock 이라는 접두어를 붙여줘야 한다.
  - InterlockIncrement : lock inc x 를 구현해 놓은 함수이다...


TIP : 함수의 어셈 코드 보기

HMODULE hdll = GetModuleHandle( " xxx.dll " );  // 함수가 포함된 dll
void* p = (void*) GetProcAddress( hdll, "함수명" );
printf( "%p\n", p );

=> 함수의 dll에서의 주소(p)를 디스어셈블리창에서 찾아보면 나온다..
Tag | ,

Trackback Address :: 이 글에는 트랙백을 보낼 수 없습니다