[NodeJS] 운영체제의 이벤트루프, nodejs의 이벤트루프
- philosophers 평가를 하다가 waiting queue에 들어간 스레드가 어떤 방식으로 다시 ready queue에 들어가는지 궁금해졌다.
- 파고들다보니, 예전에 까봤던 libuv의 이벤트루프와 매우매우 유사한 개념을 많이 공부했고, 이에 대해 다시 정리하고자한다.
운영체제의 이벤트루프?
- OS에는 이벤트루프가 존재한다.
- 저 깊은 아래 어딘거 커널단에서는 사용자의 입력, 네트워크, I/O, timer 등의 수많은 소프트웨어/하드웨어 인터럽트와 이벤트를 관리하는 구조로 만들어져있다.
- 운영체제가 해야하는 일은 매우매우매우 중대하다.
- 수많은 이벤트를 비동기적으로 처리해야한다.
- 비동기적으로 처리한다? -> 이벤트가 발생할때마다 해당 이벤트를 처리하는 콜백함수를 호출해 작업을 처리한다.
어디에 구현되어있나?
- 스케쥴러에 이벤트루프가 구현되어있다.
- 스케쥴러는 적어도 100밀리초마다 실행되며 ready queue에서 CPU를 할당할 프로세스를 선택한다.
- 인터럽트가 발생하면 운영체제는 커널 루틴을 수행할 수 있도록 context switching을 수행한다.
- nodejs의 이벤트루프는 스케쥴러의 역할과 유사하다.
- 또한, 운영체제의 interrupt handler의 개념은 nodejs에서 event handler와 비슷한 개념이다.
usleep을 쪼개서 사용해야 시간을 맞출 수 있는데, 왜?
- usleep 을 호출하면 그 이상을 sleep 하는 것을 보장한다. 즉, 완벽하게 시간을 맞추지 못한다는 의미이다.
-
하지만 왜?
- 기본적으로 usleep 하면
waiting queue
에 들어가게되는데, 이 waiting queue 등 프로세스 status별 queue의 관리는스케쥴러 쓰레드
에서 처리하게된다.
- wait queue에 들어간 프로세스, 스레드는 시그널을
일정시간 대기
하고 있다.
-
이 일정시간 대기가 핵심이다. 어떻게 시간을 확인할까?
- 컴퓨터의 timer는 하드웨어 timer와 소프트웨어 timer가 존재한다.
- 하드웨어 타이머는 1ms간격으로 timer interrupt를 발생하는 역할을 한다.
OS의 Interrupt Service Routine
에 등록된 소프트웨어 타이머는 하드웨어 타이머에 의해 발생한 interrupt를 감지하고,timer queue
를 확인한다.- timer queue에 등록된 timer에서 실행시켜야하는 timer가 존재한다면, 이에 등록된 콜백함수를 실행한다.
-
오.. 대충 느낌은 온다. 밑에서 usleep으로 확인해보자.
usleep예시
- 스레드에서 usleep 호출
- 스레드는 running queue에서 BLOCKED 상태로 바뀌면서 waiting queue로 이동한다.
- 이 스레드에는 SIGALRM 시그널 핸들러가 등록되며, 이 핸들러는 signal handler queue에 등록된다.
- 주어진 시간에 대해 timer를 timer queue에 등록한다. 이 timer의 콜백함수는 signal handler queue에 등록된 SIGALRM 시그널 핸들러를 통해 waiting queue에 있는 스레드에게 SIGALRM 시그널을 발생시킨다.
- 1ms마다 hardware interrupt가 발생하고, 이 interrupt는 스케쥴러 스레드가 timer queue를 확인하도록 한다.
- timer queue에서 대기시간이 지난 timer에 대해 콜백함수가 수행되고, signal handler queue에 등록된 SIGALRM 시그널 핸들러를 통해 waiting queue의 스레드에게 SIGALRM 시그널을 발생시킨다. 이로 인해 해당 스레드는 SIGALRM signal을 받고, SIGALRM signal handler가 실행된 후 ready queue로 이동한다. 통해
SIGALRM
sigaction으로 waiting queue의 스레드가 ready queue로 이동한다.
댓글남기기