<내용참고>
docs.oracle.com/cd/E19455-01/806-5257/gen-26/index.html
async-signal safe 연산은 인터럽트된 코드를 간섭하지 않는 것이 보장되는 연산을 의미한다.
printf()는 async-signal safe하지 않은 함수인데, signal handler에서 printf를 사용하면 어떠한 문제가 일어나는지 알아보고, 왜 signal handler에서 async-signal safe한 함수만을 사용해야 하는지 알아보자.
예를 들어 프로그램에서 printf를 수행하고 있는 도중 signal이 발생하여 printf()를 호출하는 signal handler가 호출되었다고 가정하자. 이러한 경우에 두 개의 printf() 수행은 섞여버리게 된다. (=인터럽트된 코드를 간섭하는 상황이 벌어진 것이다.)
이러한 문제점을 피하기 위해서 signal handler는 async-safe하지 않은 printf를 호출해서는 안 된다.
이러한 문제는 synchronization으로도 해결할 수 없다. 왜냐하면 deadlock에 빠져버리기 때문이다.
예를 들어 동시에 printf()를 호출하지 못하도록 mutex를 사용하여 printf() 영역을 보호한다고 가정하자.
어떤 thread가 mutex lock을 얻어서 printf를 수행하고 있던 도중 signal에 의해 interrupt되었다고 한다면,
signal handler 또한 printf를 수행하기 위해 mutex lock을 얻으려고 시도하게 된다.
이 때, 이미 mutex를 lock한 thread가 다시 mutex lock을 요청하는 상황이 벌어져 deadlock에 빠지게 되는 것이다.
이러한 상황이 일어나지 않는다는 것을 보장하기 위해서 signal handler 내부에서는 async-signal safe한 함수만 사용해야 하는 것이다.
<내용 출처>
리눅스에서 시그널이 오면 하던 일을 멈추고 당장 해당 시그널에 매핑된 시그널 핸들러를 실행하게 된다.
이 때, 이 시그널 핸들러에서는 Async-signal-safe한 함수(혹은 코드조각)만을 실행하도록 권고된다.
Async-signal-safe란, 인터럽트된 코드를 간섭(side-effect)하지 않는 것을 말한다.
정확하게는 앞서 말한 바와 같이 현재 인터럽트된 시스템 진행을 간섭하지 않으면 되는 것이지만, 인터럽트란 언제나 일어날 수 있기 때문에 특정 인터럽트된 진행을 간섭하지 않게끔 하는 것은 의미가 없고, 모든 경우에 안전해야 한다. 대표적으로 re-entrant한 함수는 safe하다.
핸들러가 Async-signal-safe하지 않고, 인터럽트된 코드 또한 Async-signal-safe하지 않다면 어떤 일이 일어날지 예측할 수 없다. 예를 들어 printf를 진행중에 인터럽트가 발생하고 이에 대한 핸들러에서 printf를 호출한다면, 출력이 뒤섞여 버리는 등의 문제가 발생할 수 있다.
만약 이를 해결하기 위해, safe-function을 만든다고 mutex등을 사용하여 동기화를 하려한다면 데드락에 빠지게 된다.
func1함수에서 락을 잡은 상태에서 인터런트 핸들러가 실행되고 핸들러에서 func1을 호출한다면, 핸들러는 먼저 실행된 func1이 락을 해제하기를 기다리고 func1은 핸들러가 종료되기를 기다리게 될 것이다.
'다전공_컴퓨터공학 > 시스템프로그래밍, 운영체제' 카테고리의 다른 글
[SP] unlink, remove (0) | 2020.12.03 |
---|---|
[SP] sleep (0) | 2020.12.01 |
[SP] write(2) return 0의 의미 (0) | 2020.10.14 |
[SP] C 컴파일, 링크 (0) | 2020.10.14 |
[SP] makeargv (0) | 2020.10.14 |