Unix 시스템에서 PID는 프로세스의 실행이나 중단과 같이 특정 프로세스를 대상으로 작업을 해야할 경우
프로세스를 지칭하기 위해서 사용
부모 프로세스 fork() 함수를 실행
-> 자식 프로세스는 fork()가 실행된 지점부터 시작됨
-> 자식 프로세스는 부모 프로세스와 동일하지 않음
-> 자신의 주소 공간, 자신의 레지스터, 자신의 PC값을 갖는다.
**
부모 프로세스와 자식 프로세스는 fork() 시스템 콜 반환값이 서로 다름
부모 - 자식 PID
자식 - 0
fork() 시스템 콜
프로세스를 생성할 때 사용된다.
자식 프로세스는 부모 프로세스와 동일하지 않음
자식 프로세스는 자신만의 주소 공간, 레지스터, 자신의 PC 값을 갖는다.
wait() 시스템 콜
부모 프로세스가 자식 프로세스가 종료될 때까지 대기할 때 사용하는 시스템 콜
해당 시스템 콜을 사용하면 항상 자식 프로세스가 먼저 실행된 뒤 종료되면 부모 프로세스가 실행되게 함
exec() 시스템 콜
자기 자신이 아닌 다른 프로그램을 실행해야 할 때 사용
-> 복사본이 아닌 다른 프로그램을 실행해야 하는 경우에 exec() 시스템 콜이 그 일을 함
-> 즉, 새로운 프로세스를 생성하지 않음
**
fork() 시스템 콜은 자신의 복사본을 생성하여 실행함
exec() 시스템 콜 수행 과정
실행 파일의 이름과 인자가 주어지면 해당 실행 파일의 코드와 정적 데이터를 읽어들여 현재 실행 중인
프로세스의 코드 세그먼트와 정적 데이터 부분을 덮어 쓴다. 힙과 스택 및 프로그램 다른 주소공간들로
새로운 프로그램의 실행을 위해 다시 초기화 함
즉, 자식 프로세스는 exec() 이후의 코드를 실행하지 않음, 자식 프로세스는 완전히 다른 프로그램이 됨
fork()와 exec() 시스템 콜을 분리한 이유
쉘이 fork()를 호출하고 exec()를 호출하기 전에 코드를 실행해야 하기 때문
- 이 때 실행되는 코드는 프로그램의 환경을 설정하고, 다양한 기능을 준비하는 코드임
병렬 처리
에러 처리 ( 자식 프로세스가 exec 호출 실패할 경우 이를 감지하고 대응 가능 )
pipe() 시스템 콜
한 프로세스의 출력과 다른 프로세스의 입력이 동일한 파이프에 연결됨
-> 한 프로세스의 출력은 다른 프로세스의 입력으로 사용되고, 명령어 체인이 형성됨
kill() 시스템 콜
프로세스에게 시그널을 보낼 때 사용하는 시스템 콜
**
시그널은 프로세스를 중단시키고, 삭제하는 등의 작업에 사용됨
시그널은 외부사건을 프로세스에게 전달하는 토대
UNIX 쉘 프로그램 실행 예시
유닉스 쉘 프로그램은 명령어가 실행되면 fork()를 호출하여 자식 프로세스를 생성하고 wait() 함수를 호출하여
대기한다. 그리고 자식 프로세스는 fork() 시점부터 실행되어 명령어에 있는 다른 프로그램을 exec() 시스템 콜
을 호출하여 실행한다. 이 때 자식 프로세스의 메모리 공간은 실행된 다른 프로그램의 메모리 공간으로 덮여쓰여지며
exec() 이후의 코드를 전혀 실행하지 않고 다른 프로그램이 되어 다른 프로그램의 코드를 실행한다.
자식 프로세스가 작업을 마치고 리턴하면, 부모 프로세스는 대기를 그만두고 다음 코드를 실행한다.
1. 쉘의 명령어 입력 대기:
쉘은 사용자로부터 명령어 입력을 기다립니다.
2. fork() 호출:
사용자가 명령어를 입력하면 쉘은 fork()를 호출하여 자식 프로세스를 생성합니다.
이 시점에서 부모(쉘)와 자식 프로세스가 동시에 실행됩니다.
3. 부모 프로세스의 wait():
부모 프로세스(쉘)는 wait() 또는 waitpid()를 호출하여 자식 프로세스의 종료를 기다립니다.
4. 자식 프로세스의 exec():
자식 프로세스는 exec() 계열 함수를 호출하여 입력된 명령어에 해당하는 새 프로그램을 실행합니다.
exec() 호출이 성공하면 자식 프로세스의 메모리 공간은 완전히 새 프로그램으로 대체됩니다.
exec() 이후의 코드는 실행되지 않습니다. 새 프로그램의 main() 함수부터 실행이 시작됩니다.
5. 자식 프로세스(새 프로그램)의 실행:
새 프로그램이 실행되어 작업을 수행합니다.
6. 자식 프로세스의 종료:
새 프로그램이 작업을 마치고 종료되면, 자식 프로세스도 함께 종료됩니다.
7. 부모 프로세스(쉘)의 재개:
wait() 상태에 있던 부모 프로세스는 자식 프로세스의 종료를 감지하고 다음 작업을 계속합니다.
보통 이 시점에서 쉘은 다음 명령어 입력을 기다리는 상태로 돌아갑니다.