리눅스는 한번에 수백여개 이상의 프로그램을 저장하고, 동시에 수행할 수 있다. 여기서 프로그램이란 어떤 문제를 해결하기 위해 사용되는 명령어나 유틸리티의 집합으로, 프로그램을 설치하면 하드디스크에 저장되고, 특정한 목적을 위해 프로그램을 실행하면 메모리(보통 RAM)에 상주하게 된다. 이렇게 실행중인 프로그램을 프로세스 라고 하고, 실행시 PID(Process Identity)가 할당되어 관리된다.
프로세스는 다음과 같이 크게 두가지로 구분할 수 있다.
사용자의 입력에 관계없이 실행되는 백그라운드 프로세스
명령 입력 후 수행종료까지 기다려야하는 포어그라운드 프로세스
프로세스에 대한 다양한 정의
실행(executing, running)중인 프로그램
PCB(Process Control Block)를 지닌 프로그램 : 프로세스를 지원하고 관리하기 위한 정보들이 담긴 데이터 구조체로, 리눅스에서는 task_struct와 함께 구현
프로그램 카운터(Program Counter)를 지닌 프로그램
능동적 개체로, 순차적으로 수행하는 프로그램
프로세스 생성
하나의 프로세스가 다른 프로세스를 실행하기 위한 시스템 호출 방법에는 fork와 exec이 있다.
fork : 새로운 프로세스를 위해 메모리를 할당받아 복사본 형태의 프로세스를 실행하는 형태로, 기존의 프로세스는 그대로 실행되어 있다. 새롭게 생성된 프로세스는 원래의 프로세스랑 똑같은 코드 기반으로 실행되며, 부모의 변수, 스택, 힙의 내용, PCB도 함께 복사한다. PCB가 복사되기 때문에, 자식은 부모가 시작한 위치에서 동일하게 시작하게 된다. fork 된 자식 프로세스는 부모 프로세스가 종료되거나 부포 프로세스에서 wait, waitpid 함수를 호출하게 되면 종료가 된다.
exec : 원래 프로세스를 새로운 프로세스로 대체하는 형태로 호출 프로세스의 메모리에 새로운 프로세스의 코드로 덮어씌워버린다.
즉, fork 는 새로운 프로세스를 위한 메모리를 할당하며, exec 은 새로운 메모리를 할당하지 않고, exec에 할당된 프로세스만 메모리에 남겨둔다.
리눅스가 부팅이 시작되면 커널이 init 프로세스(최초의 프로세스)를 발생시키고, init은 PID 1번을 할당받는다. 이후 시스템 운영에 필요한 데몬을 비롯한 비슷한 다른 프로세스들은 fork 방식으로 init 프로세스의 자식 프로세스로 생성하게 된다.
기존에 init이 PID인 루트 프로세스 였으나 이를 개선한 것이 systemd 이다.
$ ps -p 1 ef
PID TTY STAT TIME COMMAND
1 ? Ss 454:36 /usr/lib/systemd/systemd --switched-root --system --deserialize 21
pstree 명령으로 확인시 systemd 프로세스가 가장 왼쪽에 위치하고 있는데, 이는 모든 프로세스의 부모 프로세스임을 나타낸다. 보통 명령어를 실행하면 fork 형태로 수행되며, 사용자가 로그인시 bash 프로세스를 할당받고, 명령어를 내리면 fork 형태로 수행된다.
$ ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 R 1001 33780 56800 0 80 0 - 34849 - pts/1 00:00:00 ps
4 S 1001 56800 56799 0 80 0 - 29043 wait pts/1 00:00:00 bash
ps 의 PPID가 bash의 PID인 것을 확인할 수 있다.
명령어 앞에 exec를 붙이면 기본 프로세스가 교체되면서 새로운 프로세스가 할당된다.
$ ps -l
UID PID PPID F CPU PRI NI SZ RSS WCHAN S ADDR TTY TIME CMD
501 491 487 4006 0 31 0 4298956 1416 - S+ 0 ttys000 0:00.28 -zsh
501 41990 41989 4006 0 31 0 4298956 3076 - S 0 ttys002 0:00.17 -zsh
$ zsh
$ ps -l UID PID PPID F CPU PRI NI SZ RSS WCHAN S ADDR TTY TIME CMD
501 491 487 4006 0 31 0 4298956 1916 - S+ 0 ttys000 0:00.28 -zsh
501 41990 41989 4006 0 31 0 4298956 3168 - S 0 ttys002 0:00.18 -zsh
501 60938 41990 4006 0 31 0 4298956 4152 - S 0 ttys002 0:00.15 zsh
$ exec ps -l
UID PID PPID F CPU PRI NI SZ RSS WCHAN S ADDR TTY TIME CMD
501 491 487 4006 0 31 0 4298956 1844 - S+ 0 ttys000 0:00.28 -zsh
501 41990 41989 4006 0 31 0 4298956 3040 - S 0 ttys002 0:00.18 -zsh
즉, 리눅스는 init 프로세스를 중점으로 하여 이 프로세스가 fork되고, 다음에 exec을 불러서 시스템이 동작하는 것임을 알 수 있다.
종류
Foreground Process
포어그라운드 프로세스는 셀에서 명령 실행후 해당 프로세스가 종료될 때까지 기다려야하는 경우이다.
$ find / -name '*.txt' 2>/dev/null > test.txt
다음과 같이 실행된 프어그라운드 프로세스는 실제 화면에 출력되는 내용은 없고, 찾아진 결과를 test.txt 에 저장한다. 일정 시간이 지난 후 결과 확인은 test.txt 파일을 내용만 확인하면 되는데, 불필요하게 대기하게 된다. 이러한 경우 백그라운드 프로세스로 실행하면 된다.
Background Process
백그라운드 프로세스는 눈에 보이지 않게 뒤에서 실행하는 방식이다. 실행시키는 방법은 기존 프어그라운드 실행 명령 뒤에 &만 추가로 붙여서 실행하면 되며, 다중작업을 수행할 때 유용하다.
멀티태스킹은 동시에 하나 이상의 프로그램을 실행하는 것을 말한다. 사용자 입장에서 보면 다수의 프로그램들을 백그라운드 프로세스로 실행시킨 상태에서 추가로 포어그라운드 프로세스로 다른 작업을 수행할 수 있다. 사용자가 실행한 프로세스는 중간에 중지시킬 수 있으며, 백그라운드 프로세스를 포어그라운드 프로세스로 전환하거나 포어그라운드 프로세스를 백그라운드 프로세스로 전환할 수 있다.
프로세스 전환
포어그라운드 프로세스를 백그라운드 프로세스로 전환하기 위해서는 작업중인 프로세스를 대기(suspend)시켜야 되며, CTRL + z를 누르면된다. suspend는 메모리에 올라와서 작업중인 프로세스를 일시적으로 중지시키는 것을 말하며, 작업의 상태는 jobs 명령어로 확인할 수 있다.
만약 다수의 작업이 백그라운드로 수행중인 경우 fg %작업번호 명령으로 원하는 작업을 전환시킬 수 있다.
$ vi a.txt &
[1] 88418
[1] + 88418 suspended (tty output) vi a.txt
$ vi b.txt &
[2] 88682
[2] + 88682 suspended (tty output) vi b.txt
$ vi c.txt &
[3] 91159
[3] + 91159 suspended (tty output) vi c.txt
$ jobs
[1] suspended (tty output) vi a.txt
[2] - suspended (tty output) vi b.txt
[3] + suspended (tty output) vi c.txt
jobs 명령어 수행시 +와 - 기호가 표시되는 작업이 있으며, + 가 주로 처리되는 프로세스이다. 보통 사용자가 가장 늦게 실행한 프로세스에 +가 붙으며, 작업번호 없이 fg 명령어 수행시 + 가 붙어있는 작업이 포어그라운드 프로세스로 전환된다. -가 붙은 작업은 +가 붙은 작업의 다음 우선순위 작업이다.
Signal
Signal은 프로세스끼리 서로 통신할 때 사용한다. 즉, 특정 프로세스가 다른 프로세스에게 메시지를 보낼 때 시그널을 이용한다.
특정 사용자의 프로세스 정보를 확인할 때 사용. 사용자를 지정하지 않으면 현재 사용자를 기준으로 정보 출력
x
데몬 프로세스처럼 터미널에 종속되지 않는 프로세스를 출력한다. 보통 a 옵션과 결합해 모든 프로세스를 출력할때 사용한다.
l
프로세스 정보를 길게 보여주는 옵션으로 우선수누이와 관련된 PRI와 NI값을 확인할 수 있다.
e
해당 프로세스에 관련된 환경 변수 정보도 같이 출력한다.
-e
모든 프로세스를 출력한다.(-A와 같음)
-A
모든 프로세스를 출력한다.(-e와 같음 System V 계열)
f
프로세스간 상속관계를 트리구조로 보여준다.
-f
유닉스 스타일로 출력해주는 옵션으로 UID, PID, PPID 등이 함께 출력된다.
p
특정 PID를 지정할 때 사용한다.(BSD 계열)
-p
특정 PID를 지정할 때 사용한다.(SyS V 계열)
-C 프로세스명
지정한 프로세스만 보여준다.
-o 값
출력 포맷을 지정하는 옵션이다. 값으로는 pid, tty, time, cmd 등을 지정할 수 있다.
항목
항목
설명
USER
프로세스 소유자 명(BSD 계열)
UID
프로세스 소유자 명(System V)
PID
프로세스 식별번호
%CPU
CPU 사용 비율 추정치(BSD)
%MEM
메모리 사용 비율 추정치(BSD)
VSZ
K단위 또는 페이지 단위의 가상 메모리 사용량
RSS
실제 메모리 사용량(Resident Set Size)
TTY
프로세스와 연결된 터미널
STAT
프로세스 상태코드
START
프로세스 시작 시간
TIME
총 CPU 사용 시간
COMMAND
프로세스 실행 명령
STIME
프로세스가 시작된 시간(Sys V)
C, CP
짧은 기간동안 CPU 사용률
F
프로세스 플래그(1: exec 호출 없이 fork된 경우 4: 슈퍼유저 사용자)
PPID
부모 프로세스의 PID
PRI
실제 실행 우선순위
NI
nice 우선순위 번호
STAT 의 주요 값
값
의미
R(Running)
실행 중 혹은 실행 될 수 있는 상태
S(Sleeping)
인터럽트에 의한 sleep 상태 특정 이벤트가 종료되기를 기다림
D(Disk wait)
디스크 I/O에 의해 대기하고 있는 상태
T(Traced of stopped)
정지된 상태(suspend)
Z(Zombie)
좀비 프로세스를 뜻하는데, 작업이 종료되었으나 부모 프로세스로 부터 회수되지 않아 메모리를 차지하고 있는 상태
X
죽어있는 상태를 뜻
<
우선순위가 인위적으로 높아진 상태
N(Nice)
다른 사용자에 의해 인위적으로 우선순위가 낮아진 상태
L
메모리 안에서 페이지가 잠금된 상태(real-time과 I/O에 의해 발생)
s
session Leader
I
멀티 쓰레드 상태(CLONE_THREAD)
+
포어그라운드 프로세스 그룹
$ ps a
PID TT STAT TIME COMMAND
72277 s000 Ss 0:00.05 /Applications/iTerm.app/Contents/MacOS/iTerm2 --serv
72278 s000 S 0:00.05 login -fp dh0023
72279 s000 S+ 0:00.30 -zsh
79333 s001 Ss 0:00.09 /Applications/iTerm.app/Contents/MacOS/iTerm2 --serv
79338 s001 S 0:00.05 login -fp dh0023
79339 s001 S 0:00.16 -zsh
79814 s001 R+ 0:00.00 ps aa
497 s004 Ss 0:00.05 /Applications/iTerm.app/Contents/MacOS/iTerm2 --serv
498 s004 S 0:00.04 login -fp dh0023
499 s004 S+ 0:00.29 -zsh
$ ps u
USER PID %CPU %MEM VSZ RSS TT STAT STARTED TIME COMMAND
dh0023 79339 0.0 0.0 4298356 3784 s001 S 2:56PM 0:00.18 -zsh
dh0023 79333 0.0 0.1 4299336 9620 s001 Ss 2:56PM 0:00.09 /Applicati
dh0023 72279 0.0 0.1 4298416 4444 s000 S+ 2:51PM 0:00.30 -zsh
dh0023 72277 0.0 0.1 4307528 9636 s000 Ss 2:51PM 0:00.05 /Applicati
dh0023 499 0.0 0.1 4298416 4264 s004 S+ 1:19PM 0:00.29 -zsh
dh0023 497 0.0 0.1 4307528 7200 s004 Ss 1:19PM 0:00.05 /Applicati
$ ps x
PID TT STAT TIME COMMAND
330 ?? S 0:00.10 /System/Library/Frameworks/LocalAuthentication.frame
332 ?? S 0:03.11 /usr/sbin/cfprefsd agent
334 ?? S 0:03.22 /usr/libexec/UserEventAgent (Aqua)
336 ?? S 0:04.58 /usr/sbin/distnoted agent
337 ?? S 0:00.36 /System/Library/PrivateFrameworks/CloudServices.fram
338 ?? S 0:01.16 /usr/libexec/knowledge-agent
339 ?? S 0:00.62 /usr/sbin/universalaccessd launchd -s
340 ?? S 0:12.09 /usr/libexec/trustd --agent
$ kill -l
HUP INT QUIT ILL TRAP ABRT EMT FPE KILL BUS SEGV SYS PIPE ALRM TERM URG STOP TSTP CONT CHLD TTIN TTOU IO XCPU XFSZ VTALRM PROF WINCH INFO USR1 USR2
예시
# 프로세스 강제 종료(-9 KILL, SIGKILL)
$ kill -9 756 778 7700
# 프로세스 재시작(HUP or -1)
$ kill -HUP 10118
# 작업번호로 프로세스 종료
$ kill %2
# 기본 종료 시그널인 TERM을 보내어 종료
$ kill -s SIGTERM 1702
killall
같은 데몬의 여러 프로세스를 한번에 종료시킬 때 사용하는 명령어로, 프로세스 명을 사용한다.
$ killall [option] 프로세스명
옵션
설명
-l
시그널 종류 출력(--list)
-w
시그널을 받은 프로세스들이 종료될 때까지 기다린다.(--wait)
-v
시그널 전송된 결과 출력(--verbose)
-s signal
시그널의 이름 지정(--signal)
-u 사용자명
특정 사용자의 프로세스를 지정할 때 사용(--user)
예제
# Apache 웹 서버 데몬인 httpd를 모두 종료
$ killall httpd
# httpd 데몬을 재실행
$ killall -HUP httpd
# httpd 데몬에 9번(KILL, SIGKILL)을 전송하고, 전송결과 출력
$ killall -v -9 httpd
# example 사용자의 모든 프로세스 강제 종료
$ killall -u example
jobs
백그라운드로 실행중인 프로세스나 현재 중지된 프로세스 목록 출력
$ jobs [option]
옵션
설명
-l
PID 번호를 추가 출력
fg
백그라운드 프로세스를 포어그라운드 프로세스로 전환하는 명령
$ fg [%Job_number]
$ fg [Job_number]
# 백그라운드로 수행중인 작업이 여러 개라면, 가장 최근에 수행한 작업(+기호가 붙어있는)을 포어그라운드로 전환
$ fg
bg
포어그라운드 프로세스를 백그라운드 프로세스로 전환하는 명령 : 포어그라운드로 실행중인 프로세르에 ctrl + z 를 눌러 작업을 일시 중지 시킨 후 bg명령을 사용해서 백그라운드로 전환할 수 있다.
$ bg
nice
프로세스의 우선순위를 변경하는 명령어로, NI값을 설정할 때 사용한다. 프로세스에 설정되어 있는 NI 기본값은 0이고, 지정 가능한 범위는 -20~19이며, 작을 수록 우선순위가 높다. 일반 사용자는 NI값을 증가시키는 것만 가능하며, root만 NI값을 감소시켜 우선순위를 높일 수 있다.
$ nice [option] 프로세스명
옵션
설명
-n 값, - 값
--adjustment=값
프로세스에 설정된 NI값을 지정한 NI값과 증감한다. 값을 지정하지 않으면 기본 10이다.