Linux 프로그램, 프로세스, 쓰레드
프로그램
프로그램이란, HDD 또는 SSD에 저장된 실행가능한 바이너리 코드(0100011...)
프로세스
프로세스란?
프로그램이 RAM에 로드되어 있는 상태.
* 비유 : 프로세스 = 작업장 / 쓰레드 = 일꾼
multi-process = 프로세스가 여러개
새 프로세스 생성 시
- Windows : 맨땅에서 process를 새로 만듬
- Linux : fork() 함수를 사용하여 기존 process를 복제해서 만듬.
부모/자식 프로세스란?
부모 프로세스 : 복제를 수행한 프로세스
자식 프로세스 : 복제된 프로세스
자식 프로세스가 모종의 이유로 죽을 경우, Linux kernel은 부모 프로세스에게 자식 프로세스가 죽었다는 signal을 보낸다. 이 signal이 바로 '종료 코드(종료 상태)'다.
프로세스 아이디(PID)란?
프로세스를 구분하기 위해 프로세스에게 부여되는 고유 아이디. 0이상의 정수값을 가짐.
* PPID = 부모 프로세스의 PID
ps
PID TTY TIME CMD
14 tty1 00:00:00 bash
44 tty1 00:00:00 ps
명령어 ps를 수행하면 로그인한 사용자가 현재 실행되고 있는 프로세스의 목록을 볼 수 있다.
ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 10:40 ? 00:00:00 /init
root 13 1 0 10:40 tty1 00:00:00 /init
hello 14 13 0 10:40 tty1 00:00:00 -bash
hello 45 14 0 10:45 tty1 00:00:00 ps -ef
만약 다른 사용자가 실행하고 있는 프로세스의 목록을 확인하고 싶다면 ps -ef를 통해 Linux 시스템의 모든 프로세스 목록을 확인할 수 있다.
top
결과>
Tasks: 4 total, 1 running, 3 sleeping, 0 stopped, 0 zombie
%Cpu(s): 2.7 us, 1.4 sy, 0.0 ni, 95.8 id, 0.0 wa, 0.2 hi, 0.0 si, 0.0 st
KiB Mem : 67010176 total, 58838092 free, 7942732 used, 229352 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 58933712 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 8972 428 348 S 0.0 0.0 0:00.04 init
13 root 20 0 9320 240 188 S 0.0 0.0 0:00.00 init
14 hello 20 0 16804 3480 3384 S 0.0 0.0 0:00.04 bash
42 hello 20 0 17632 2092 1556 R 0.0 0.0 0:00.02 top
프로세스의 목록과 각 프로세스 별로 CPU와 메모리 사용량을 볼 수 있다.
사용량은 자동으로 3초에 한번씩 갱신된다.
Enter : 수동으로 사용량 갱신
q : 종료
프로세스 간 통신 : 시그널
프로세스 간 통신에는 크게 2가지 방법이 있다 : 1) pipe, 2) signal
시그널은 어떤 프로세스에게 특정 사건이 발생하였음을 알리는 메커니즘이다.
만약 어떤 프로세스가 시그널을 받고 아무 동작도 취하지 않는다면, 디폴트로 프로세스는 종료된다.
시그널의 종류
kill -l 명렁어를 통해 시그널의 종류를 확인할 수 있다.
kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
총 64번까지 있는데 34번부터는 realtime signal이다.
우리가 명렁어를 종료할 때 자주 사용하는 ctrl + C를 누르는 행위도 시그널을 보내는 것이다.
그럼 어떤 시그널을 보내는 것일까? stty -a를 통해 확인이 가능하다.
stty -a
speed 38400 baud; rows 30; columns 120; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = M-^?; eol2 = M-^?; swtch = M-^?; start = ^Q; stop = ^S;
susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0;
-parenb -parodd -cmspar cs8 hupcl -cstopb cread -clocal -crtscts
-ignbrk brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc ixany imaxbel iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke -flusho -extproc
CTRL + C는 interrupt(SIGINT(2)) 시그널을 보내고 CTRL + D는 EOF를 보내는 것을 확인할 수 있다.
다만, 주의할점이 프로세스에 따라 SIGINT 시그널을 받아도 종료되지 않을 수 있다.
프로세스가 수신된 시그널에 따른 동작이 정의되어 있다면, 종료되지 않을 것이다.
시그널 SIGKILL(9)
그 어떠한 Linux 프로그램도 SIGKILL 시그널에 따른 동작을 정의하지 못한다.
즉, SIGKILL 시그널을 보내면 프로그램은 반드시 죽는다.
시그널 전송방법
kill은 시그널을 보내는 명령어다.
kill -signal number pid 또는 kill -signal name pid를 이용해서 시그널 전송 가능.
# SIGINT(2) 전송
kill -2 311
kill -int 311
# SIGKILL(9) 전송
kill -kill 300
kill -9 300
종료 코드
'종료 코드'는 자식 프로세스가 종료된 이유를 부모 프로세스에게 알리기 위한 용도로 사용된다.
0~255의 값을 가지며, 0인 경우 정상적으로 종료되었음, 0이 아닌 경우 비정상적으로 종료되었음을 나타낸다.
어떤 프로세스가 시그널에 의하여 종료된 경우,
종료코드 = 128 + 시그널 번호
예를 들어, SIGINT(2)를 받아 종료되었다면 종료코드는 130이 된다.
echo $?를 통해 종료코드를 확인할 수 있다.
echo $?
+번외.
echo $!
마지막 명령어로 실행된 명령어의 PID 값을 출력
echo $$
현재 쉘의 PID값을 출력