fork() is the name of the system call that the parent process uses to "divide" itself ("fork") into two identical processes. After calling fork(), the created child process is an exact copy of the parent except for the return value of the fork() call.
This includes open files, register state, and all memory allocations, which includes the program's executable code.
In some cases the two continue to run the same binary,
but often one (usually the child) switches to running another binary executable using the exec() system call.
fork()는 시스템 콜인데 이 친구는 부모 프로세스가 자기자신을 2개의 동일한 프로세스들로 나눌 때 사용한다.
fork()가 호출된 후 자식 프로세스는 반환 값을 제외하고 부모 프로세스와 동일하다.
이는 오픈 파일, 레지스터 상태, 모든 메모리 부여, 프로그램의 실행가능한 코드가 부모 프로세스와 동일하다는 의미이다.
(아무튼 부모 프로세스와 동일하다는 설명인듯)
어떤 경우엔 2개(부모, 자식) 프로 모두 같은 바이너리에서 실되는 경우도 있지만
대부분 자식 프로세스가 exec() 시스템 콜을 통해 다른 바이너리에서 돌아간다고 한다.
When a process forks, a complete copy of the executing program is made into the new process.
This new process is a child of the parent process, and has a new process identifier (PID).
The fork() function returns the child's PID to the parent process.
The fork() function returns 0 to the child process.
This enables the two identical processes to distinguish one another.
프로세스가 fork하면 새로운 프로세스(완벽한 복제 프로그램)가 만들어지게 되는데
이 새로운 프로세스는 부모 프로세스의 자식이 되며 새로운 PID를 가지게 된다.
fork() 함수는 부모 프로세스에겐 자식 프로세스의 PID를 반환하고,
자식 프로세스에겐 0을 반환한다.
이렇게 해줌으로 2개의 동일한 프로세스가 (부모와 자식으로)구분된다.
If the parent chooses to wait for the child to die,
then the parent will receive the exit code of the program that the child executed.
To prevent the child becoming a zombie the parent should call wait on its children,
either periodically or upon receiving the SIGCHLD signal, which indicates a child process has terminated.
부모 프로세스가 자식 프로세스의 종료를 기다릴 때
부모 프로세스는 실행 중인 자식 프로세스의 exit code를 받게 된다.
자식 프로세스가 좀비가 되는 것을 방지하기 위해 부모 프로세스는 자식 프로세스들의 신호를 기다려야 한다.
신호는 주기적인 신호나 자식 프로세스가 종료되었을 때 보내는 SIGCHLD 신호를 말한다.
One can also asynchronously wait on their children to finish, by using a signal handler for SIGCHLD,
if they need to ensure everything is cleaned up.
Here's an example of a signal handler that catches any incoming SIGCHLD signals and handles multiple concurrent signals received.
모든 자식 프로세스가 종료된 것을 확인해야 할 경우
다른 방법으로 신호 핸들러인데 SIGCHLD 신호 핸들러를 사용해 자식 프로세스의 종료를 비동기적으로 기다릴 수 있다.
아래는 들어오는 SIGCHLD 신호를 캐치하고 다중 동시 신호 수신해 처리할 수 있는 코드 예제이다.
void cleanup(int signal) {
while (waitpid((pid_t) (-1), 0, WNOHANG) > 0) {}
}
결론 : fork() 시스템 콜은 하나의 프로세스를 복제해서 다른 PID를 부여하는 것으로 이해했다.
When the child process calls exec(), all data in the original program is lost,
and it is replaced with a running copy of the new program.
This is known as overlaying.
Although all data are replaced, the file descriptors that were open in the parent are closed only if the program has explicitly marked them close-on-exec.
This allows for the common practice of the parent creating a pipe prior to calling fork()
and using it to communicate with the executed program.
자식 프로세스가 exec() 시스템 콜을 호출하면 원래 있던 프로그램의 데이터는 전부 날라간다.
그리고 새로운 프로그램의 실행 코드로 갈아치운다.
(오버레잉이라고도 부르나보다)
모든 데이터가 바뀌어도 부모에서 열어둔 파일 디스크립터들은
명시적으로 close-on-exec로 표현해줘야 닫을 수 있다.
이를 통해 부모가 fork()를 호출하기 전에 파이프를 만들고
이를 사용하여 실행된 프로그램(자식 프로세스)과 통신하는 일반적인 관행을 허용한다.
Microsoft Windows does not support the fork-exec model,
as it does not have a system call analogous to fork().
The spawn() family of functions declared in process.h can replace it in cases
where the call to fork() is followed directly by exec().
마이크로소프트 윈도우는 fork-exec 모델을 지원하지 않는다.
이는 fork와 유사한 시스템 콜을 가지고 있지 않기 때문이다.
fork()에 대한 호출 다음에 exec()가 직접 오는 경우
process.h에 선언된 spawn() 함수 패밀리가 이를 대체할 수 있다고 한다.
결론 : exec() 시스템 콜은 복제한 프로그램을 원하는 프로그램으로 바꿔주는 걸로 이해했다.
reference
https://en.wikipedia.org/wiki/Fork%E2%80%93exec
'background > linux kernel' 카테고리의 다른 글
[Lazenca][Development of Kernel Module] 03.ioctl(Input/Output control) (0) | 2024.03.28 |
---|---|
[Lazenca][Development of Kernel Module] 02.Character Device Drivers (0) | 2024.03.28 |
[Linux Kernel] Device Driver (0) | 2024.03.28 |
[Lazenca][Development of Kernel Module] 01.Hello world! (0) | 2024.03.28 |
시스템 호출(system call) (0) | 2022.09.06 |