목차
- 유닉스 쉘이 하는 일
- 유닉스의 프로세스 모델
- 프로그램을 실행하는 법
- 프로세스를 어떻게 만드는가
- 부모와 자식 프로세스간 통신하는 법
- 시스템콜
- fork
- exec
- wait
- exit
- command
- sh
- ps
Program과 Process
- program: 기계어 명령어와 데이터 덩어리 => 파일, 데이터의 의미
- process: 프로그램이 실행되고 있는 메모리 공간과 환경 => processes are programs in action
- running a program: 프로그램의 명령어들을 메모리에 적재하고, 프로세서(CPU)가 하나씩 실행함
Command
ps
현재 process들을 나열
- PID : process ID
- TTY : terminal type, 유저가 로그인하고 있는 콘솔 또는 터미널의 이름(ex: pts/5)
- TIME : CPU time
- CMD
ps -la

- S : status
- S : sleeping (일시 중단)
- R : running
- UID : 누가 이 process를 실행시키는가
- PPID : parent process ID
Computer Memory & Computer Program
- 유닉스 시스템에서 메모리는 커널 영역과 유저 영역으로 나뉨
- 프로세스는 유저 영역에 있음, 커널 영역을 침범해선 안됨
- 프로세스는 디스크 파일로서 메모리에 디스크 블록(pages)으로 나뉘어 저장되어 있음
The shell
- shell
shell = program launcher
프로그램을 메모리에 적재하고 실행시킬 수 있다.
- -bash
리눅스에서는 기본 -bash 쉘을 사용한다
- sshd
쉘을 실행시켜주는 쉘 데몬
계속 백그라운드에서 동작함(쉘을 실행시켜주기 위해 항상 대기 중)
모든 프로세스의 부모 프로세스, 제거하면 다 종료됨
Shell의 프로그램 실행 원리

- user가 a.out을 타이핑한다 (input)
- shell은 프로그램을 실행시킬 new process를 생성한다
- shell은 디스크에 저장된 프로그램(파일)을 찾아 프로세스(새로운 공간)에 적재한다
- $ which ls : 파일 위치 알려줌
- /usr/bin/ls : ls 프로그램이 저장된 위치
프로그램은 그 프로세스 안에서 실행된다
어떻게 실행하는가? => execvp() 시스템콜
execvp(proname, arglist)
명령어에 대한 실행결과를 알려주는 거, shell처럼 동작하는 명령어
main() {
char *arglist[3];
arglist[0] = "ls";
arglist[1] = "-l";
arglist[2] = "0";
printf("* * * About to exec ls -l\n");
execvp("ls" arglist);
printf("* * * ls is done. bye\n"); // 출력되지 않음
}
왜 두 번째 printf문은 출력되지 않을까?
execvp는 command(process)를 만나면 그 프로세스로 변하기 때문에. 실행 후 exit.
해결법: 새로운 프로세스가 필요함 => fork() 시스템콜을 사용하여 현재 프로세스를 복제함

fork()

원래 프로세스를 새로운 프로세스에 완전히 복제
새로운 프로세스는 fork() 이후부터 실행함