자주 발생하는 수신 대기 중 발생되는 에러 리스트

 

1. ERROR_SEM_TIMEOUT( 121 )

The semaphore timeout period has expired.

장비(방화벽 또는 라우터) 이상 또는 제한으로 인한 네트워크 단절(랜선을 뽑는 경우도 포함)이 발생했을 때

 

2. ERROR_NETNAME_DELETED( 64 )

The specified network name is no longer available.

보통 IOCP에서 소켓 끊어짐의 상징은 0 byte read다.

0 byte read가 통보되는 시점은 상대방 소켓에서 closesocket() 혹은 shutdown() 함수를 호출한 시점임

즉, 상대방이 closesocket() 혹은 shutdown() 을 호출하지 않고 종료해버리면 일반적으로 0 byte read는 발생하지 않는다.

이렇게 0 byte read가 발생하지 않은 상태에서 read() 혹은 write()를 시도하면 상대는 이미 종료 되었으므로

ERROR_NETNAME_DELETED 에러가 나게 됨.

 이러한 경우를 우아한 종료와는 반대되는 개념으로 HardClose라고 함.

 

 

3. WSAENOTSOCK( 10054 )

An operation was attempted on something that is not a socket.

지정한 소켓은 정상 적이지 않습니다(INVALID_SOCKET). 별도의 종료처리없이 소켓을 닫으면 나옴.

 

 

4. ERROR_IO_PENDING( 997 )

펜딩은 수신중이라 걍 패쓰

 

 

 

5. ERROR_OPERATION_ABORTED( 995 (

The I/O operation has been aborted because of either a thread exit or an application request.

1. 작업이 취소된 사례. CreateIoCompletionPort에 추가한 핸들(소켓)이 닫혔을 때.

 클라이언트가 연결된 상태에서 서버가 먼저 종료하면 발생.(server socket이 close되어서)

2. 동시에 송수신할 때

 CreateIoCompletionPort에 핸들(소켓)을 추가하기 전에

 WSADuplicateSocket 이나 DuplicateHandle 를 이용해 핸들을 복사하여 분리해서 추가해주면 된다

   고 한다.

 

 

 

 

 

 

 

 

'Server' 카테고리의 다른 글

크리티컬섹션, 뮤텍스  (0) 2012.09.04
데드락  (0) 2012.09.04
3way hand shake  (0) 2012.08.13
라우팅  (0) 2012.08.13
OS의 종류와 차이점  (0) 2012.08.13

I/O 방법별 성능 비교

Posted 2012. 10. 17. 14:04

NetWork Programming for Microsoft Windows 책. Chaper 6.


I/O 모델 

 연결시도 /연결 성공

메모리

사용량(KB) 

Non-page

pool 

CPU

사용량 

스레드

개수 

처리량

(send/recv bytes per second) 

 Blocking

7000/1008

12000/1008 

25,632

25,408 

36,121,

36,353 

10~60%

5~40% 

2016 

2198148/2198148

404227/402227

 non-blocking

7000/4011

12000/5779 

4208

5224 

135,123

156,260 

95~100%

95~100% 

0/0

0/0 

WSAAsync

Select

7000/1956

12000/5779 

3640

4884 

38246

42992 

75~85%

90~100% 

3

1610204/1637819 

652902/652902

 WSAEvent

Select

7000/6999

12000/11080

46000/45933 

10502

19214

37392 

36402

39040

121624 

65~85%

50~60%

80~90% 

113

192

791 

4921350/5186297 

3217493/3217493

3851152/3834511

 Overlapped

(event)

7000/5558

12000/12000

49000/48996 

21844

60576

241208 

34944

48060

155480 

65~85%

35~45%

85~95% 

66

195

792 

502423/4095644

1803878/1803878 

3865152/3834511

overlapped

( c p ) 

7000/7000

12000/12000

50000/49997 

36160

59256

242272 

31128

38862

148192 

40~50%

40~50%

55~65% 

2

2

6282473/3893507 

5027914/5027095

4326946/4325496

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 



locked page, non-paged pool

Posted 2012. 10. 17. 13:50

서버는 충분한 리소스가 없더라도 수천 개의 연결을 처리 할 수 있어야 한다.

서버가 연결을 더 많이 받아들일수록 점점더 리소스의 한계치에 도달하게 된다.

서버가 고려해야 되는 리소스의 종류가 locked page(잠겨진 메모리 페이지) 와 non-page pool(

페이징 되지않은 메모리풀) 두 가지 리소스가 있다.

locked pages의 한계는 non-paged pool 고갈보다 덜 심각하고 처리하기 쉽다.


1) locked pages

모든 overapped i/o 호출시에는 호출에 사용한 데이터 버퍼가 잠겨질(lock) 가능성이 있다.

메모리가 잠겨지면 물리적 메모리로 페이징되지 않는다.

OS는 잠겨질 수(locked)있는 메모리의 한계를 정해 놓고 있다. 이 한계에 도달하면

overapped i/o 호출은 WSAENOBUFS로 실패한다.

서버가 각 연결마다 많은 수의 overapped i/o를 호출하면 연결이 증가될수록 이 한계치에 도달할 확률

이 높아진다. 만일 서버가 동시에 아주 많은 수의 연결을 처리해야 한다면 각 연결별로 0 바이트 크기의

수신용 overapped i/o 를 한번씩만 호출하는 방법을 사용 할 수 있다.

이런 경우 수신용으로 할당된 버퍼가 없으므로 잠겨지는(locked) 메모리가 없다.

또한 이런 방식을 사용할때는 소켓의 수신 버퍼의 크기는 바꾸지 않아야 한다.

왜냐하면 0 바이트의 overapped i/o작업이 완료 되면 논블록킹 수신으로 소켓버퍼에 있는 데이터를

가져와야 하기 때문이다.이때 넌 블록킹 수신이 WSAEWOULDBLOCK를 반납하면 소켓 버퍼에 더이상

읽을 데이터가 없는 것이다.

이러한 설계는 각 연결별 데이터 처리 능력을 희생해서 서버의 연결 용량을 증가시키는 방법이다.

또 하나 고려해야 할 사항은 서버가 구동되고 있는 시스템의 메모리 페이지 크기이다.

시스템은 overapped i/o에 전달된 메모리를 페이지 단위로 lock한다. x86에서는 페이지는 4KB의

배수로 lock 된다. 만일 overapped i/o로 1KB의 버퍼를 전달했다면 시스템은 이 버퍼를 포함한 4KB를

lock한다. 따라서 메모리 낭비를 막기 위해서는 버퍼를 페이지 단위(페이지의 배수)로 사용 해야 한다.

GetSystemInfo함수를 호출하면 시스템에서 사용하는 페이지 크기를 얻어 올 수 있다.

SYSTEM_INFO sysInfo;

GetSystemInfo( &sysInfo );

해보면 sysInfo 안에 dwPageSize로 4096 으로 되어 있다.



2) non-page pool

한계치에 다다르는 경우는 문제를 해결하기가 어렵다.

non-page pool은 물리적 메모리에 상주하면서 페이징 되지 않는영역이다.

드라이버와 같은 커널모드 콤포넌트 들이 non-page pool을 사용하는데 윈속과 tcpip.sys와 같은

프로토콜 드라이버들도 여기에 속한다. 소켓을 생성 할 때마다 소켓의 상태정보를 저장하기 위한

용도로 작은 양의 non-page pool이 소비된다. 여기에 추가로 소켓이 특정 주소에 바인드되면

TCP/IP스택은 로컬 주소 정보를 저장하기 위한 용도로 non-page pool을 할당한다.

결과적으로 연결된 소켓은 2KB, accept나 acceptEX에 의해 리턴된 소켓은 1.5KB의 non-page pool을

소비한다.( accept, acceptEX에 의해 리턴도니 소켓은 리모트 주소만 저장하므로) 또한

각 overapped i/o 별로 IRP( I/O request packet)를 발생시키면서 대략 500바이트의 non-page pool을

소비한다. 연결별로 사용되는 non-page pool은 얼마되지 않는다.하지만 연결이 증가할수록 non-page 

pool의 문제는 심각해진다. 1GB의 물리적 메모리를 갖춘 windows에서 서버가 동작중이라 가정하면

이런경우 256MB가 non-page pool로 사용 될 수 있다. 보통 non-page pool은 windows2000 이상의

버전에서는 물리적 메모리의 4분의1이 한계이다. windows NT4.0에서는 128MB가 한계이다.

서버가 50,000개 이상의 연결을 관리한다고 생각해보면 여기에는 데이터의 송신과 수신용 overapped i/o뿐만 아니라 연결수락(accept)용 overapped i/o작업도 고려해야 한다. 이 경우 accept나 acceptex

에 의하여 생성된 소켓으로 75MB의 non-page pool을 소비한다. 0 바이트의 overapped I/O호출 기법을 사용한다고 가정하면 ITP에 의해 25MB의 non-page pool이 소비된다.



시스템에서 non-page pool이 부족하면 나타나는 증상은 두가지 이다.

운이 좋은 경우 윈속 함수가 WSAENOBUFS에러를 발생시킨다. 그렇지 않을 경우 시스템이

에러로 손상(crash)될 수 있다. 이런 에러는 non-page pool을 회복하는 방법이 없다.

더군다나 사용가능한 non-page pool을 알아보는 방법도 없다. 결국 얼마나 많은 수의 연결과

overlapped i/o작업이 가능한지 경정하는 프로그래밍 기법이나 정해진 한계치가 없다.

non-page pool이 부족하거나 locked page가 초과된 경우 모두 WSAENOBUFS에러를 발생하므로

둘을 구별하는것도 불가능하다. 이런 이유로 개발자는 반드시 서버의 연결 용량과 overlapped i/o

작업의 용량을 테스트해봐야 한다. non-page pool의 부족이 프로그래밍적으로 일어나지 않도록 막았다면 WSAENOBUFS 에러가 locked page의 초과로 인해 발생됬다고 가정하고 더 이상의 overlapped

i/o작업을 금지하거나 몇개의 연결을 닫는것으로 에러를 피할수 있다.




서버는 대용량 처리용 서버와 대량 연결용 서버로 나눌 수 있다.

대용량 처리용 서버

1. 각 연결에 대하여 전송 시간을 최소화 시켜야 한다.

이런 목적으로 서버는 동시에 연결 할 수 있는 수를 제한해 놓은 경우가 많다.

제한 함으로써 많아 졌을때 연결별로 처리 능력이 떨어지는 현상을 방지 할 수 있다.

일정수의 연결을 세트로 해서 처리하는 방법이 있다.

예를 들어 서버는 클라의 연결을 100개씩 FIFO방식으로 처리한다. 첫번째 100개를 처리하면

큐에 쌓여있던 다른 100개의 클라를 처리한다. 송수신 I/O작업은 연결별로 일정수를 유지

할 수 있다. 따라서 클라는 연결이 증가됨에 따라 서버의 I/O작업이 무작정 늘어나서 리소스가

고갈되는 것을 방지 할 수 있다.

악의적인 클라에 의해 서버가 공격받는것을 방지하기 위해서는 서버에서는 각 연결별로

I/O작업이 발생되는 수를 체크해야 한다. 예를 들어 서버가 클라의 데이터를 수신하도록

설계되어 있다면 얼마나 보내졌는지 응답하는 구조로 사용한다. 클라는 서버에게 데이터를

마구 보내면서 응답하지 않는다면 많은 수의 overlapped i/o 송신이 누적 될 것이다.

이런경우 서버는 이 연결을 종료 해야한다.

IOCP와 버퍼의 관계

Posted 2012. 10. 17. 12:16

IOCP는 data를 전송하거나 수신할때 WSAOVERLAPPED 구조체 및 버퍼를 생성하여

넘겨주어야 하는데 클라가 수천개나 되는 경우 시스템 입장에서 보면 메모리를 너무 많이 잡아 먹는다.

NETWORK PROGRAMMING for Microsoft WINDOWS책에는.

대량 연결용 서버의 경우 0 SIZE 버퍼를 사용하여 IO작업을 요청하라. 고 되어있다.

0 SIZE 버퍼를 사용하면 메모리 사용은 현격히 줄어든다.

wsabuf.buf = NULL; << 버퍼를 제공하지 않는다.

wsabuf.len = 0; << receive할 최대 크기를 0로 만든다.

flag = 0;


이러면 해당 소켓으로 데이터가 들어오면 IOCP는 worker thread를 깨워 처리하도록 한다.

그런데 문제는 버퍼가 없으니 받은 데이터가 없다는 거다.

worker thread에선

일반적으로 bytes 값이 0 이면 연결이 끈긴 것으로 처리했지만 0 size버퍼를 사용했을 경우는

무조건 bytes값이 0으로 리턴된다.

이 경우 끈긴 것으로 판단하지 말고 일단 데이터가 들어온 것으로 파단해야 한다.

버퍼를 0로 만들었기 때문에 IOCP는 소켓으로 수신된데이터를 아직 손대지 않은 상태다

이것을 알아 낼 때엔 IOCP를 사용하지 않은 일반적인 socket프로그램으로 읽으면 된다.

nonblocking방식으로 WSAEWOULDBLOCK이 될때까지 recv를 하면 된다.

(block일경우 프로토콜의 정의된 데이터만큼 recv 하면되고..)

이렇게 데이터를 모두 읽어서 처리 했다면 WSARecv를 사용하여 IOCP에게 요청하면 된다.



으흠..

받는쪽은 일단 버퍼 크기를 좀 크게 설정해 준다.

받는쪽이 0이 되버리면 send에서 에러가 나는 이유기도 하고 보냇는데 못받으면 그게

더 큰 문제이기 때문에..

SNDBUF, RCVBUF

Posted 2012. 10. 17. 12:03

1) 소켓 버퍼의 싸이즈 : 디폴트 싸이즈 -> 8192(8KB)

2) 옵션 : SO_SNDBUF, SO_RCVBUF

3) 버퍼 복사 구조 SND과정 : User Buf -> Socket Buf -> TCP Buf

옵션으로 SND 버퍼를 0으로 만들게 되면 User Buf -> TCP Buf 로 Socket Buf를 건너 뛰게 된다.

한 단계의 copy를 줄이게 되는 것. RCV는 반대상황이고 마찬가지고 한단계의 copy를 줄이게 된다.

이렇게 되면 RCV할때 User Buf로 copy속도가 충분히 빠르지 않을 경우 RCV는 TCP의 허용가능한

window size를 줄이고, SND시 TCP로 지속적으로 데이터를 주는데 제약을 가하며

TCP 통신 처리량을 줄이는 병목의 원인이 된다.

이럴 경우 보다 충분한 수의 overapped i/o를 요청을 미리 호출해 줘야 한다.


또는 그냥 비동기 방식으로..


이건 IOCP에 써야겟다



Socket의 옵션

Posted 2012. 10. 16. 16:15

1. SO_RCVBUF, SO_SNDBUF

이 옵션은 TCP의 소켓 옵션에 해당한다.

이 옵션을 설정하면 커널의 송/수신 버퍼의 크기를 조정 할 수 있다.

(커널 : 운영체재의 핵심부분으로 메모리에 상주하면서 시스템에 존재하는 자원을 관리한다)

응용프로그램이 원격지로 전송하는 자료는 일단 송신버퍼에 복사되어 있다가

원격지의 수신버퍼로 전송된다. 수신버퍼는 전송받은 자료를 응용프로그램이 읽어갈때까지 보관한다.

수신버퍼의 크기가 작으면 버퍼외의 자료를 수신측에서 모두 버려진다.

TCP에선 흐름제어를 통해 connect함수나 listen함수의 연결준비 단계에서 수신버퍼의 크기를

기준으로 송수신 버퍼값을 설정한다. 하지만 그렇다 하더라도 커널이 그대로 적용하지 않고

값을 참조한뒤 커널의 정책에 따라 버퍼의 크기를 결정한다.

즉, 적용한 버퍼의 값이 실제로 적용되지 않을 수 있다.




2. SO_REUSEADDR

이 옵션은 커널이 소켓을 사용하는 중에도 계속해서 사용 할 수 있게 하는 옵션입니다.

커널이 소켓을 사용하게 되는건. 연결 종료 과정에서 먼저 연결 종료를 시작한 쪽은 상대방으로 부터

FIN패킷을 받고 FINM_ACK패킷을 전송한 후 일정시간동안 종료하지 않고 커널이 해당 소켓을

점유할 때를 말한다. 이렇게 먼저 종료를 시작하는 시스템은 응용프로그램이 종료를 하더라도

소켓은 커널에서 일정시간동안 점유중인 상태로 있게 된다. 이런 경우 응용프로그램을 재실행하면 

bind를 호출할때 아직 점유중인 포트를 연결하려는 시도 때문에 오류가 난다.

일정 시간이 지나면 다시 접속이 가능 하지만 온라인게임서비스에서 일정 시간을 딜레이하는건

다소 무리가 있다. 이럴때 이 옵션을 사용하면 점유중에서도 연결이 가능하게 해준다.


3. SO_LINGER

이 옵션은 close함수를 호출할때 송신버퍼의 자료가 모두 전송된 것인지 확인인 하지 않고 종료를 할

것인지 정하는 옵션이다. TIME_WAIT관련..




4. TCP_NODELAY

Nagle알고리즘에 관련된 옵션이다.

Nagle알고리즘은 가능하면 여러번 보내지 말고 한번에 많이 보내는 원칙을 기반으로 만들어진것.

그리고 ACK를 수신해야만 다음 전송을 진행한다.

TCP는 기본적으로 Nagle알고리즘이 적용되어 있다.

적은양을 모으다 보면 통신량은 줄어들지만 지연될 수 있는 단점이 있다.

또한 사용하지않고 마구 보내게되면 전송량이나 부하가 커진다.

그냥 끄고 스케쥴러 사용하자



Socket의 종료( closesocket )

Posted 2012. 10. 16. 15:13

소켓의 종료는 closesocket함수를 호출하면 종료 하게 된다.

하지만 단순히 closesocket만 호출하면 문제가 발생 할 수 있다.

그 문제가.. 온라인게임을 서비스 하는 입장이라면 단순하지 못한 문제..


closesocket를 호출 했을때 어떻게 종료가 되는지 흐름을 알아야 한다.

1. A가 B에게 연결 종료를 요청한다

2. B는 종료전 할 일이 남아있기 때문에 FIN를 보내지않고 ACK만 보내고 CLOSE_WAIT 상태로 넘어간다.

-> 할 일이란. 송(수)신버퍼상 남아있는 데이터를 모두 전송하는 작업임

3. 작업이 끝난 후 B는 FIN를 보내고 연결을 종료하고자 한다.

4. A는 B의 FIN을 잘 받았다는 ACK를 B에게 보내게 되고 A의 ACK를 받으면 B는 종료한다.

문제는 4번 과정에서 A는 ACK를 보내고 소켓이 제거될때까지 TIME_WAIT라는 상태에 있게 되는데

(약 4분)이 TIME_WAIT에 빠지는 이유는 A가 B로 보낸 마지막 종료 메세지 이후 바로 종료하면

라우터나 기타네트워크 상에서 발생하는 문제들에 의해 마지막 종료 메세지가 B에 도착 하지 못했을때

생긴다. 그러면 B는 종료하지 못하고 다시 A에게 마지막 FIN을 보내게 된다.

여기서 A가 TIME_WAIT가 아니라 강제종료된 상태라면 이 마지막 FIN역시 무시됬을테고 B는 여전히

A가 어떤상태인지 모르고 대기하게 된다.표준대기시간인 4분동안...


이게 무슨 문제냐면.. TCP규정상 TIME_WAIT상태일때 그 포트를 다른 프로세서가 이용하지 못하게

막아 두었다. 그래서 해당 소켓을 사용 하지 못하게 된다.


사용할수 있는 포트가 65535개나 되고 일정시간(약4분)이 지나면 사용 할 수 있게 되는데

이게 무슨 문제가 되겠냐.. 하면


로그인을 처리하는 로그인서버를 보면..

유저가 100만명인 게임이 잘 돌아가다가 예기치 못하게 서버 다운이 되었을 경우

서버를 재가동할때 100만명의 유저가 한번에 몰리게 된다.

이런경우 4분만에 포트를 다 소비하지 않는다고 장담 할 수가 없다..

이 같은 경우도 생각 해 두어야한다.


이럴때를 대비해 socket옵션에서 SO_LINGER를 사용해 대기없이 바로 종료하게 하면 된다.

간단히 끝날 문제를 대비해두자. 그냥 넘어갈 이유는 없다.

TCP의 특징

Posted 2012. 10. 16. 14:44

1. 연결 지향적이며 재전송 한다.

연결 지향적이란건 내부적으로 3way hand shake라는 기능이 있기 때문임.

이건 connect 이전에 먼저 실행되어 접속해도 되는지 안되는지 알아보는 작업 입니다.

3번의 패킷을 주고 받음으로 최종 접속여부가 가려지게 된다. 재전송은 hand shake라는게

받았다는 응답이없을면 다시 보내지게 된다.

대기시간과 횟수조절에 옵션으로 설정이 가능하다.


2. 데이터는 스트림으로서 순차성이 있다.

네트워크상에서 목적지까지 다른 방향으로 갈수가 있다.

이 과정에서 데이터가 섞이는 것을 방지하기 위해 TCP는 각 패킷에 순서를 매기낟.


3  흐름제어를 수행한다.

송신자가 수신자가 감당하기 힘들정도로 빨리 보낸다면 수신자의 버퍼는 넘쳐버리게 된다.

이런흐름을 제어하는 기법엔 G-Back-N ARQ가 있고 슬라이딩기법이 있다.

이중 슬라이딩 기법을 사용한다. 슬라이딩 기법은 수신자의 ACK응답 상황에 따라 송신자의 전송버프가

커졌다 줄었다 하면서 송신량을 조절하는 기법이다.


4. 포트를 이용해 서비스를다중화 한다.

TCP는 1:1 통신 방법이다. 포트라는 개념이 있어 우리가 사용하는 어플리케이션용 포트를하나씩 할당

해주면 각각의 어플리케이션에선 자신에게 할당된 포트를 용해 데이터를 주고 받을 수 있다.

OSI 7계층

Posted 2012. 10. 16. 14:35

국제표준기구(OSI)에서 7개의 컴퓨터 통신용 프로토콜층을 설명한 개방형 시스템 상호접속

참조모델을 구성 한 것이다.

각 게층별로 특정 기능이 있고, 이것을 사용하는 이유는 여러 정보통신업체 장비들 간 호환성이

필요하기 때문이다.


7) 응용계층( Application Layer )

: 응용 프로세스간의 정보를 교환한다. 사용자가 응용프로그램을 통해 네트워크 환경을 이용 할 수 있도록 응용프로세스간 정보 교환을 실현해 준다. TELNET, FTP등등 각종네트워크관련 프로그램들이 해당된다.

6) 표현계층( Presentation Layer )

: 데이터 형식 설정 및 코드 변환.

운영체제, 파일시스템과 관련이 있으며 서버와 클라이언트간의 상이한 데이터 표현 방식 및 부호체계를 서로 변환하여 주는 서비스를 제공한다.

또한 데이터의 보안을 유지하기 위해 암호화에 관련한 사항들을 규정함으로써 응용 계층의 통신을 도와주는 계층이다.

5) 세션계층( Session Layer )

:송수신 측에서 표현계층에서 사용할 데이터의 교환을 위한 세션과 대화방식을 결정한다.

즉 통신세션을 구성하는 계층으로 포트연결 이라고도 한다.

4) 전송계층( Transport Layer )

:네트워크 내에서 신뢰성있게 전달하기 위해 가상회로를 구축하고 유지와 종료 그리고 전소 ㅇ오류 검출 과 복.... 즉 4단계 TCP를 사용할지 UDP를 사용할지.. 선택한 것에 대한 작업

3) 네트워크 계층( Network Layer )

:두 시스템간의 연결성과 경로선택을 제공한다. 그리고 패킷을 발신지로부터 목적지로 전달할 책임을 갖는다. 

2) 데이터링크 게층( Data Link Layer )

: 네트워크게층으로 부터의 메시지를 비트로 변환하여 네트워크 바툻

1) 물리계층( Phisical Layer )

: 전기적 신호를 전송한다. 받은프레임을 비트단위의 신호로 바꾸어 하드웨어적인 주소를 사용하여 물리적인 전송매체를 통해 전달하는 일.

즉 데이터링크계층에서 만들어진 데이터를 전기신호나 광신호로 바꾸어 송수신하는 역할.



크리티컬섹션, 뮤텍스

Posted 2012. 9. 4. 14:59

크리티컬 섹션

크리티컬 섹션 오브젝트를 이용해 임계영역( 접근 제어가 필요한 영역 ) 에 하나의 스레드만 접근 할 수 있도록 하는 동기화 방법

유저레벨의 동기화 방법중 유일하게 커널 객체를 사용하지 않음

내부 구조가 단순하여 동기화 처리에 대한 속도가 빠르다

동일한 프로세스내에서만 사용 가능

커널객체를 사용하지 않기 때문에 핸들을 사용하지 않고 CRITICAL_SECTION이라는 정의를 사용

이미 Lock() 상태인 크리티컬섹션에 대해 다른 쓰레드가 Lock()을 호출하면 크리티컬섹션이 Unlokc() 될때까지 대기하도록 유도하는 구조

따라서 여러개의 스레드가 동기화 하려면 반드시 하나의 크리티컬 섹션을 공유해야 한다.

각 스레드 마다 별도의 크리티컬 섹션을 사용하는 경우 동기화는 불가능 하다.

 

뮤텍스

두개 이상의 스레드가 동시에 공통자원에 접근하지 않도록 하기 위해서 만들어진 알고리즘

커널 객체중 유일하게 소유권 개념을 가지고 있다.

스레드의 ID가 0( 유효하지 안는 스레드ID ) 면 뮤텍스의 소유권은 어느 스레드에게도 없다는 의미이고 뮤텍스 오브젝트는 시그널 된 상태이다

스레드 ID가 0이 아닌 값이면 해당 쓰레드가 소유권을 가지면 뮤텍스 오브젝트는 non-signal상태다

뮤텍스를 해제할때의 ID와 생성할때 설정한 쓰레드의 ID가 맞지 않으면 해제를 실패하고 시스템은

해당 뮤텍스의 시그널 상태를 기다리는 다른 쓰레드를 스케쥴링 한다

뮤텍스의 소유권을 가진 스레드가 뮤텍스를 해제하지 않고 종료되면 시스템은 해당 뮤텍스를 abandoned 상태로 두고 이 뮤텍스를 기다리는 스레드를 찾아 기다리고 있는 스레드에 뮤텍스의 소유권을 주고 해당 스레드를 스케쥴링 한다

 

두 가지의 차이

크리티컬 섹션은 단일 프로세스의 스레드에 대해서만 동작하고 뮤텍스는 여러 프로세스의 스레드에 대해서도 동작한다

 

 

커널 객체 : 커널( kernel ) 에서 관리되는 객체를 말하며 그 종류는 파일객체, 쓰레드객체, 이벤트 객체, 뮤텍스객체, 세마포어 객체 등이 있다.

특징

접근 하는 방식이 다른 객체와 틀리다. 보통 객체들은 사용자가 직접 접근하여 데이터를 바꾸고 추가하고 지울수 있지만 커널객체는 윈도우즈가 제공하는 특정한 함수를 사용하여야만 가능하다. 외관적으로 보기에는 커널객체는 우리가 생성하는 것처럼 보일 수 있지만 실제로 생성을 하는 것은 커널이다. 우리는 단지 그것을 생성해 달라고 특정한 함수를 이용해 커널에거 요청을 하고 커널은 요청을 받아 그 객체에 대한 메모리 공간을 할당하고 객체를 식별해주는 핸들 이란 것을 우리에게 반환해 준다

커널 객체의 소멸 시점이 틀리다

커널 객체가 아닌 다른 객체의 경우 보통은 객체를 생성한 프로세스가 소멸하면 객체도 같이 소멸하지만 커널객체는 그것을 생성한 프로세스가 소멸한다고 꼭 같이 소멸하는 것이 아니다. 이유는 모든 커널 객체에는 데이터멤버로서 usage count라는 것을 가지고 있는데 이것은 객체가 생성될때 1로 되었다가 다른프로세스들이 그 커널객체의 접근권한을 가지게 될떄 usage count는 1씩 자동적으로 증가하고 접근 권한을 가진 프로세스소멸할떄 usage count는 1씩 자동감소한다. 그래서 커널은 그 커널객체의 usage count가 0이 될떄 객체를 소멸한다

스케쥴링 : 처리할 일들의 진행순서. 즉 우선순위를 정하는 일

 

'Server' 카테고리의 다른 글

Connection Error] IOCP : GetQueuedCompletionStatus  (0) 2013.10.18
데드락  (0) 2012.09.04
3way hand shake  (0) 2012.08.13
라우팅  (0) 2012.08.13
OS의 종류와 차이점  (0) 2012.08.13