티스토리 뷰

[2017/09/09 추가]

포스팅 후에 피드백을 받았습니다. 원래 글은 IBM 및 다른 블로그, 책 등을 참조해서 작성했었는데, 애초에 IBM 블로그가 오류가 있다고 하네요. 

인터넷 상에 IBM 블로그를 기초로 작성된 글들이 많은데요, 밑에 원글도 그대로 두니 비교 참조하시길 바랍니다.


async : 이벤트 핸들러 (callback)에 의해 처리 (callback 함수가 호출되기까지 다른 작업 가능)

sync : 이벤트를 자신이 직접 처리(확인의 주체가 유저 프로세스이며, 다 될때까지 기다리거나 스스로 확인)

block : 완료까지 대기(리턴되기 전까지 멈춤)

non-block : 미완료라도 즉시 리턴


간단히 까페에서 커피를 주문하는 것을 예로 들어보면,

1. 커피를 타달라는 요청이 왔다. 

2-1. 이 때 커피가 있으면 타준다(블로킹/넌블로킹 모두)

2-2. 커피가 없는 경우 블로킹 : '잠깐만요'하고 사러 간다. / 넌블로킹 : 커피가 없다고 말하고 사러 간다.

3-1. 동기 : 커피가 타졌는지 안타졌는지 내가 확인한다.

3-2. 비동기 : 벨이 울리면 받으러 간다.


즉, 이범주로 보면 select는 sync + non-block으로 보는 것이 맞다고 합니다.(async + block 사례는 뭐가 있을까요..)

추가적으로, signal-driven I/O도 async + non-block 으로 보는 것이 맞다고 합니다.

(일반적인 async는 non-block인걸로..)


보다 자세한 내용은 SLiPPTCP/IP Review & I/O Model 을 참조하시는게 좋을거 같네요.




유저단계의 프로세스는 I/O 작업을 직접 수행할 수 없으며, 커널에게 요청해야 한다. 

운영체제가 제공하는 서비스를 호출하는 함수를 시스템 호출(system call)이라고 한다.

Blocking I/O과 Non-Blocking I/O

Blocking : 유저 프로세스가 시스템 호출을 하고나서 결과가 반환되기까지 다음 처리로 넘어가지 않음 
Non-Blocking : 호출한 직후에 프로그램으로 제어가 돌아와서 시스템 호출의 종료를 기다리지 않고 다음 처리로 넘어갈 수 있음      

Synchronous I/O와 Asynchronous I/O

동기 : 작업을 요청한 후 작업의 결과가 나올 때까지 기다린 후 처리 (프로세스는 커널에 지속적으로 I/O 준비사항을 체크)
비동기 : 직전 시스템 호출의 종료가 발생하면 그에 따른 처리를 진행  




Synchronous blocking I/O


가장 기본적인 I/O 모델로, 파일을 읽고 쓰는 일반적인 read, write와 같은 I/O 시스템 호출을 의미한다. (특별한 설정이 없으면 blocking으로 동작한다.)
유저 프로세스가 read()을 호출한 후 커널은 데이터가 사용자 버퍼에 복사되기 전까지 리턴하지 않으며, 유저 프로세스는 자신의 작업을 중단한 채 대기한다. (CPU 등의 자원 낭비)
따라서, 여러 클라이언트가 접속하는 서버를 Blocking방식으로 구현할 경우 하나의 클라이언트가 I/O 작업을 진행하면 해당 프로세스(또는 쓰레드)가 진행하는 작업을 중단하게 되므로, 클라이언트별로 프로세스(또는 쓰레드)를 만들어 연결시켜야 한다. 하지만 접속자 수가 증가하면 프로세스(또는 쓰레드)가 증가한다.



Synchronous non-blocking I/O


커널은 data를 읽은 후 버퍼에 저장하고 그 내용을 유저에게 복사해준다. 버퍼는 커널이 가지고 있는 메모리에 적재되므로 메모리간 복사가 일어나 I/O보다 빠른 속도로 받아올 수 있다. 그러나 버퍼가 비어있다면 커널은 즉시 에러(EWOULDBLOCK)를 반환하여, 유저 프로세스가 지속적으로 read()을 호출하여 I/O 준비사항을 체크하도록 한다. (polling 방식) 이에 반복적으로 시스템 호출이 일어나므로 cpu 등의 자원이 낭비된다.



Asynchronous blocking I/O  ( 이부분이 오류가 있다고 하네요. )


select나 poll과 같은 시스템 호출을 이용하여 I/O 다중화를 하기 위한 목적으로 사용된다.
(select와 poll은 여러개의 descriptor에서 데이터가 준비되었는지 검사를 수행하여 준비가 된 descriptor가 발견될 경우 리턴하여 여러 개의 I/O를 처리할 수 있다. 다만, select는 관리 file descriptor 수에 제한이 있고, poll은 제한은 없으나 file descriptor 당 체크 마스크의 크기가 커서 접속자 수가 늘어나면 성능이 떨어진다.)



Signal-driven I/O


미리 sigaction() 시스템 호출을 하여 시그널 핸들러를 미리 등록한 후 커널에 데이터가 준비되었을 경우 SIGIO 라는 시그널을 발생시켜 데이터의 도착을 알려주는 모델이다.
이 모델은 데이터가 준비되기 전까지 어플리케이션은 block되지 않으므로 유저 프로세스는 다른 작업을 처리하거나 대기하면 된다.



Asynchronous non-blocking


aio_read() 시스템 호출을 하면 file descriptor와 buffer의 포인터, buffer의 크기 및 file offset, 완료시 통지 방법 등을 커널에 전달하고, 커널은 즉시 리턴한다. 이 후 데이터가 사용자 버퍼에 복사되어 I/O 준비가 완료되면 시그널을 발생하여 완료를 알려준다.





참조 : SLiPPDeveloperWorksShicao's Notes Developer StoryTistory Studio





'Programming > .common' 카테고리의 다른 글

RESTful API란 ?  (10) 2017.11.08
'객체 지향과 디자인 패턴' 후기  (0) 2017.10.02
blocking vs non-blocking / synchronous vs asynchronous  (0) 2017.09.01
Travis CI 적용하기  (0) 2017.08.24
[Command]Git 명령어 정리  (0) 2017.08.07
테스트 환경 구축하기  (0) 2017.08.01
댓글
댓글쓰기 폼
링크
«   2020/04   »
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    
Total
93,570
Today
50
Yesterday
168