반응형

본 글은  컴퓨터 밑바닥의 비밀  2.7 장 내용을 요약한 내용입니다.

 

블로킹와 논블로킹

  • 함수를 호출할 때 주로 사용됨

함수 A, B가 있다고 가정

함수 A가 B를 호출할 때, 함수 B를 호출함과 동시에 OS가 함수 A가 실행중인 스레드나 프로세스를 일시 중지 시킨다 → 블로킹

그렇지 않으면 → 논-블로킹

  • 블로킹 호출 핵심은 스레드/프로세스가 일시 중지되는 것

모든 함수 호출이 호출자의 스레드를 일시 중지 시키는 것은 아님

int sum(int a, int b)
{
	return a + b;
}

void func()
{
	int r = sum(1, 1);
}
  • 위 코드는 운영체제가 func 함수 호출 시 해당 스레드를 중지시키지 않음. 핵심은 입출력

 

블로킹의 핵심 문제: 입출력

  • 입출력 요청 완료시간은 CPU의 클럭 주파수보다 훨씬 느림
  • 입출력 과정이 실행되는 동안 CPU 제어권을 다른 스레드로 넘겨 다른 작업을 할 수 있도록 해야 함
  • 이후 입출력 작업이 완료되면 다시 CPU제어권을 우리 쓰레드/프로세스로 받아와 다음 작업을 실행할 수 있도록 함

  • CPU 제어권을 상실했다가 되찾는 시간 동안 블로킹되어 일시 중지됨
    • 스레드 A가 입출력 작업을 실행하여 블로킹되면 CPU는 스레드 B에 할당됨
    • 스레드 B가 실행되는 동안 OS는 입출력 작업이 완료된 것을 확인하면 다시 스레드 A에 CPU 할당

 

논블로킹과 비동기 입출력

네트워크 데이터 수신을 예로 설명. 데이터를 수신하는 함수인 recv가 논블로킹이면 이 함수를 호출할 때 OS는 스레드를 일시 중지시키는 대신 recv 함수를 즉시 반환

  • 호출 스레드는 자신의 작업을 계속 진행하고 데이터 수신 작업은 커널이 처리

데이터를 언제 수신했는지 알 수 있는 방법은?

  1. 논블로킹 방식의 recv 함수 외에 결과를 확인하는 함수를 함께 제공하고, 해당 함수를 호출하여 수신된 데이터가 있는지 확인
  2. 데이터가 수신되면 스레드에 메시지나 신호등을 전송하는 알림 작동 방식
  3. recv 함수를 호출 할 때 데이터 수신 처리를 담당하는 함수를 콜백 함수에 담아 매개변수로 전달할 수 있음(recv 함수가 콜백 함수를 지원해야 함)

논블로킹 호출이며, 이런 유형의 입출력 작업을 비동기 입출력 이라고도 함

피자 주문에 비유하기

  • 피자를 직접 주문하러 피자가게에 가서 주문하고 기다려 받는것: 블로킹
  • 피자 전화로 주문 후 받는 것: 논 블로킹
    • 피자 완성됬는지 계속 체크하면? 동기
    • 일반적으로는 비동기

동기와 블로킹

  • 블로킹 호출은 확실한 동기 호출
  • 동기호출은? 블로킹 호출이 아닐 수 있음
    • sum 함수에 대한 호출은 동기이지만 funcA가 sum 함수 호출을 했다고 해서 블로킹되거나 하지 않음
int sum(int a, int b)
{
	return a + b;
}

void func()
{
	int r = sum(1, 1);
}

 

비동기와 논블로킹

네트워크 데이터 수신을 예로 들어 설명

  • 데이터를 수신하는 recv 함수를 논블로킹 호출로 설정하기 위해 flag 값 추가(NON_BLOCKING_FLAG)
void handler(void *buf)
{
	//수신된 네트워크 데이터를 처리
}

while(true)
{
	fd = accept();
	recv(fd, buf, NON_BLOCKING_FLAG, handler); // 호출 후 바로 반환, 논블로킹
}
  • recv 함수는 논블로킹 호출 → 네트워크 데이터를 처리해주는 handler 함수를 콜백 함수로 전달, 즉 비동기이자 논 블로킹

하지만 데이터 도착을 감지하는 전용 함수인 check 함수를 제공해서 아래와 같이 구성한다면,

void handler(void *buf)
{
	//수신된 네트워크 데이터를 처리
}

while(true)
{
	fd = accept();
	recv(fd, buf, NON_BLOCKING_FLAG, handler); // 호출 후 바로 반환, 논블로킹
	
	while (!check(fd))
	{
		// 순환 감지
		;
	}
	
	handler(buf);
}
  • while 문에서 끊임없이 데이터를 도착하기 전까지 체크하기 때문에 그 전에 handler 함수를 사용할 수 없음 ⇒ recv 함수는 논블로킹이지만 전체적인 관점에서 이 코드는 동기

정리하면, 논블로킹이더라도 전체적으로 반드시 비동기라는 의미는 아님

반응형

'OS' 카테고리의 다른 글

[책리뷰] 컴퓨터 밑바닥의 비밀: ch3.1 메모리의 본질, 포인터와 참조  (0) 2024.08.25
Event loop와 coroutine  (0) 2024.08.11
동기/비동기  (0) 2024.08.10
파일 시스템  (0) 2024.07.28
가상 메모리(Virtual memory)  (0) 2024.07.28

+ Recent posts