Operating System
Mutex
뮤텍스는 화장실에 들어가기 위한 열쇠로 비유할 수 있다. 즉, 화장실에 들어갈 수 있는 열쇠를 한 사람이 갖고 있다면 한 번에 한 사람만이 들어갈 수 있다. 화장실에 열쇠를 갖고 있는 사람이 들어가 볼 일을 다 본 후에 줄을 서서 기다리고 있는(대기열-큐) 다음 사람에게 열쇠를 주게 된다.
뮤텍스는 한 번에 하나의 쓰레드만이 실행되도록 하는 재 입장할 수 있는 코드 섹션에 직렬화된 접근이 가능하게 할 때 사용된다. 뮤텍스 객체는 제어되는 섹션에 하나의 쓰레드만을 허용하기 때문에 해당 섹션에 접근하려는 다른 쓰레드들을 강제적으로 막음으로써 첫 번째 쓰레드가 해당 섹션을 빠져나올 때까지 기다리도록 한다.
뮤텍스는 값이 1인 세마포어이다.
Semaphore
세마포어는 빈 화장실 열쇠의 개수라고 보면 된다. 즉, 네 개의 화장실에 자물쇠와 열쇠가 있을 때 세마포어는 열쇠의 개수를 계산하고 시작할 때 4의 값을 갖게 된다. 이 때는 이용할 수 있는 화장실 수가 동등하게 된다. 이제 화장실에 사람이 들어갈 때마다 숫자는 줄어들게 된다. 4개의 화장실에 사람들이 모두 들어가게 된다면 남은 열쇠가 없기 때문에 세마포어 카운트가 0이 된다. 이제 다시 한 사람이 화장실에서 볼 일을 다 보고 나온다면 세마포어의 카운트는 1이 증가된다.
세마포어는 공유 리소스에 접근할 수 있는 최대 허용치만큼 동시에 사용자 접근을 할 수 있게 한다. 쓰레드들은 리소스 접근을 요청할 수 있고, 세마포어의 카운트가 하나씩 줄어들게 되며 리소스 사용을 마쳤다는 신호를 보내면 세마포어 카운트가 하나 늘어나게 된다.
fork()와 exec()
fork()와 exec()는 모두 한 프로세스가 다른 프로세스를 실행시키기 위해 사용한다.
fork() 시스템 호출은 새로운 프로세스를 위한 메모리를 할당한다. 그리고 fork()를 호출한 프로세스를 새로운 공간으로 전부 복사하게 되며, 새로 생성된 프로세스는 원래의 프로세스와 똑같은 코드를 가지게 된다. 원래 프로세스는 원래 프로세스대로 작업을 실행하고 fork()를 이용해서 생성된 프로세스도 그 나름대로 fork() 시스템 콜이 수행된 라인의 다음 라인부터 실행이 된다.
exec()는 fork()처럼 새로운 프로세스를 위한 메모리를 할당하지 않고, exec()를 호출한 프로세스가 아닌 exec()에 의해 호출된 프로세스만 메모리에 남게 된다. 즉, exec()의 결과로 생성되는 새로운 프로세스는 없고, exec()를 호출한 프로세스의 PID가 그대로 새로운 프로세스에 적용이 된다. Exec는 execl, execv등 여러 가지 함수 군을 가지고 있다.
정리하면, fork()의 결과는 프로세스가 하나 더 생기는 것이다. 따라서 PID가 다르다. 반면, exec()의 결과는 기존의 프로세스가 새 프로세스로 대체되는 것이다.
Context switching
CPU는 동시에 한 개씩의 쓰레드만 실행시킬 수 있다. 쓰레드가 여러 개가 생성되면 CPU는 각각의 쓰레드를 시분할하여 각각의 쓰레드를 번갈아 가며 실행하게 되는데, 이 때 이전 쓰레드의 문맥 정보(레지스터 값, 실행 중인 스택 정보 등)을 백업 받고, 백업 받아 놓았던 다음 쓰레드의 문맥 정보를 로딩하는 과정을 Context Switching(문맥 교환)이라고 한다.
문맥은 프로세스의 PCB(Process Control Block)에 표현되며, CPU 레지스터의 값, 프로세스의 상태, 메모리 관리 정보 등을 포함한다. CPU를 다른 프로세스로 교환하려면 이전의 프로세스의 상태를 보관하고, 새로운 프로세스의 보관된 상태를 복구하는 작업이 필요하고, 이를 문맥교환(Context Switch)라고 한다.
메모리와 레지스터 사이의 데이터 이동도 I/O 이다. 즉, 컨텍스트 스위칭 과정에서 I/O가 발생한다. 빈번한 오버헤드를 발생시킨다. 실행되는 프로세스의 수가 많고, 빈번한 컨텍스트 스위칭이 발생한다면 이는 시스템 성능을 떨어뜨린다.