fork() 시스템 콜프로세스를 생성할 때 사용된다.

현재 실행중인 프로세스의 복사본을 생성한다. 운영체제가 새로운 프로세스를 생성하고 이 새로운 프로세스는 원본 프로세스의 메모리 공간을 복사하여 가지게 된다. 그러나 완전히 동일하지는 않다. 각각 고유한 주소 공간, 레지스터, PC 값을 가진다.
fork()로부터 부모 프로세스는 생성된 자식 프로세스의 PID를 반환받고, 자식 프로세스는 0일 반환받는다. rc값이 다르기 때문에 서로 다른 코드를 실행하는 프로그램을 쉽게 작성할 수 있다.

이 프로그램의 출력결과가 항상 동일한 것은 아니다. CPU 스케줄러에 의해 실행할 프로세스를 정하기 때문에 어느 것이 먼저 실행된다고 단정할 수 없다.
이런 비결정성으로 인해 멀티 쓰레드 프로그램에서 다양한 문제가 발생한다. → 병행성 부분에서 자세히 다룰 예정이다.
wait() 시스템 콜
부모 프로세스가 자식 프로세스의 종료를 대기하기 위해 사용된다. 부모 프로세스는 자식의 작업이 완료될 떄까지 블록되며, 자식이 종료 후 wait()가 리턴된다.

wait() 시스템 콜을 통해 위 프로그램은 항상 동일한 결과를 출력하게 된다.
wait()를 통해 자식의 종료를 기다리기 때문에 자식 프로세스에서 먼저 프린트한다.exec() 시스템 콜자기 자신이 아닌 다른 프로그램을 실행해야할 때 사용한다.

exec() 에 실행 파일 이름과 인자가 주어지면, 해당 실행 파일의 코드와 정적 데이터를 현재 실행 중인 프로세스에 덮어쓰고 힙과 스택 영역이 새롭게 초기화 된다. 현재 실행중인 프로그램을 새로운 것으로 대체하게 되는 것이기 때문에 기존의 프로그램은 리턴하지 않게된다.

execvp() 시스템 콜을 호출 시, 자식 프로세스의 메모리 공간이 wc 프로그램으로 대체되고, 기존 자식 프로세스는 리턴되지 않게된다(Line 21이 실행되지 않음).
Unix의 쉘을 구현하기 위해서 fork()와 exec()을 분리해야 한다. 그래야만 fork()를 호출하고 exec()를 호출하기 전에 코드를 실행할 수 있다. 이때 프로그램의 환경을 설정하고 다양한 기능을 준비한다.

해당 작업을 실행하기 위한 코드는 다음과 같다.


p4를 실행하면, 화면에 아무 일도 일어나지 않는다. 그러나 실제로는 다음과 같은 일이 발생하였다.
fork()를 호출하여 새로운 자식 프로세스를 생성한다.execvp()를 호출하여 wc프로그램을 실행시킨다. cat해 보면 wc를 실행시켰을 때 얻을 수 있는 모든 출력이 파일에 저장되어 있다.Unix의 파이프가 이와 유사한 방식으로 구현된다. 다만 pipe() 시스템 콜이 사용된다. 한 프로세스의 출력과 다른 프로세스의 입력이 동일한 파이프에 연결된다. 한 프로세스의 출력이 자연스럽게 다른 프로세스의 입력으로 사용되고 명령어 체인이 형성된다.
$ grep fo file | wc -1 과 같은 명령어를 생각하면 좋다.
kill() - 프로세스에게 시그널을 보내는데 사용된다. 시그널은 프로세스를 중단(block) 시키고, 삭제하는데 사용된다.ps - 어떤 프로세스가 실행 중인지 확인 간으top - 시스템에 존재하는 프로세스와 이것들이 CPU 및 다른 자원을 얼마나 사용하는지 확인 가능