Whenever a program wants to cuase an effect outside its own process, it must ask the kernel for help.
Example: read/write files
fopen internally calls open, where a system call is invoked.
Our program can directly call open, too. (included <fcntl.h>)
We will call this wrapper function (open) as a system call, too.

Almost all system-level operations can fail.
You must explicitly check for failure.
On error, Linux system-level functions typically return -1 and set global variable errno to indicate cause.
Process ID: a unique integer ID assigned to each process
pid_t getpaid(void) //returns PID of current process
pid_t getppid(void) //returns PID of parent process
Note: Every process has a parent process
Process is either executing, or it is waiting to be selected by kernel and run. (active한 상태로 보는 게 더 정확하다.)
Process execution is suspended and will not be scheduled until further notice (커널이 context switch를 할 때 선택의 후보지에 없는 상태)
Process is finished but the parent process has not yt been notified. (프로그램이 종료되었다고 그 즉시 프로세스가 사라지는 건 아니다. parent process가 terminate된 프로세스를 처리해야 하는데 아직 그 처리가 되지 않은 상태)
Process becomes terminated for one of two reasons
Even when your main returns, exit is called implicitly.
void exit(int status)
Terminates with an exit status of status
Convention: normal return status is 0, nonzero on error
Another way to explicitly set the exit status is to return an integer value from the main routine
*Exit is called once but never returns.
Parent process creates a new running child process by calling fork
pid_t fork (void)
Returns 0 to the child process, child's PID to parent process
Child is almost identical to parent. Child has a different PID than the parent.
fork is called once but returns twice


How can our program distinguish parent and child?
By checking the return value
When process terminates, it still consumes system resources
Called a "Zombie"
Performed by parent on terminated child (using wait or waitpid)
Parent is given exit status information
Kernel them delets zombie child process
If any parent terminates without reaping a child, then the orphaned child will be reaped by init process (the ultimate ancestor) So, only need explicit reaping in long-running processes (부모가 종료되어야 자식이 init process에 입양되는데 쉘처럼 오랫동안 돌아가는 프로그램은 부모 프로세스가 종료되기 전에 자식 프로세스에게 줄 수 있는 pid가 동날 수 있다. 줄 수 있는 pid는 한정되어 있고 zombie process가 reaping되어야 pid를 수거해올 수 있는데, reaping되지 않은 zombie process가 쌓이면 pid가 동나는 일이 발생할 수 있다.)
Parent reaps a child with one of these system calls:
pid_t wait(int* status)
Suspends current process until one of its children terminates
Returns PID of child, records exit staus in status
pid_t waitpid(pid_t pid, int* status, int options)
More flexible version of wait
Can wait for a specific child or group of children (wait와 다르게 순서 지정 가능)
Can be told to return immediately if there are no children to reap
If status != NULL, then the integer it points to will be set to a value that indicates the exit status
Must be decoded, using macros defined in sys/wait.h
WIFEXITED //True를 return하면 exit system call을 호출해서
종료됐다는 뜻
WEXITSTATUS //child process에서 exit system call을 부를 때
어떤 정수값을 전달했는지를 알 수 있다.
WIFSIGNALED //signal message를 받아서 이로 인해 종료됐다는 뜻
WTERMSTG
WIFSTOPPED
WSTOPSIG
WIFCONTINUED
If multiple children completed, will take in arbitrary order

pid_t waitpid(pid_t pid, int &status, int options)
Suspends current process until specific process terminates

int execve(char* filename, char* argv[], char* envp[])
Loads and runs in the current process:
Executable file filename can be object file or script file beginning with #!interpreter
with argument list argv (By convention argv[0] _is set to _filename)
and environment variable list envp
Overwrites code, data, and stack
Called once and never returns except there is an error
fork함수를 호출할 때: 프로세스를 만들어서 새 프로그램을 실행하고 싶을 때.
쉘이라는 프로그램이 실행되고 있을 때 ls 엔터를 치는 순간 새로운 프로세스를 만들어서 ls라는 프로그램을 실행해달라고 요청하는 것.
fork로 만들어진 프로세스는 부모의 클론. 새로운 프로그램을 실행할 수 있도록 하는 또다른 시스템콜이 필요한데 그게 execve. ls를 치면 filename이라는 문자열 인자가 ls를 담고 있고 커널에서는 ls라는 프로그램을 읽어들여서 프로그램에 있는 코드, 데이터를 현재 프로세스에 잘 옮겨줘서 ls를 실행할 수 있는 상태로 만들어줌. 성공적으로 시스템콜 호출이 일어나면 새로운 프로그램을 로드해서 실행하기 시작함. execve에서 return하지 않음. execve 밑에 pritnf가 있으면 그건 절대 실행되지 않음. 새롭게 로드된 프로그램이 실행되고 그 프로그램이 종료되는 순간 execve를 호출한 프로그램도 종료됨.

libc_start_main이 return 0이라고 하면 0이 _exit에 대한 인자로 전달됨. libc_start_main은 implicit하게 그 작업을 해줌. 컴파일되는 과정에서 슬쩍 섞여들어감. main함수 호출, main함수 return값을 가지고 exit systemcall을 호출.
이런 정보를 찾고 있었습니다, 감사합니다.