##############
## 프로세스 ##
## 4.18 ##
##############
o 프로세스란 ?
- 프로세스는 실행중인 프로그램이다.
- 프로그램은 하드디스크에 파일형태로 저장되어 있다.
- 프로그램은 실행 시에 프로세스를 어떻게 만들지에 대한 광범위한 정보를 담고있는 파일이다.
o 프로세스의 상태
신규 : 프로세스가 생성된 상태
준비 : 프로세스가 처리기의 배정을 기다리고 있는 상태
실행 : 프로세스의 명령이 실행되고 있는 상태
대기 : 프로세스가 어떤 사건이 발생하기를 기다리고 있는 상태
종료 : 프로세스의 실행이 종료된 상태
signal +---------+ signal
.--------- | 중단 중 | <------.
| +---------+ |
v |
+----------+ --------------> +--------+ +--------+
--->| 실행준비 | scheduling | 실행중 | ---> | Zombie |
+----------+ <-------------- +--------+ +--------+
^ |
| input/output(완료) | input/output
| +---------+ |
`--------- | 중단 중 |<------'
+---------+
o 프로세스의 생성
- 한 프로세스는 다른 프로세스를 fork()를 이용하여 생성하고 exec() 에 의해서 실행한다.
- 부모 프로세스 (parent process) : 자식 프로세스를 만드는 프로세스
- 자식 프로세스 (child process) : 부모 프로세스에 의해 생성된 프로세스
- 부모와 자식은 자원의 일부 혹은 전부를 공유하거나 운영체제로부터 자원을 할당 받는다.
부모 프로세스는 자식 프로세스가
+---------------+ 종료되기까지 Wait 상태 +---------------+
---> | 부모 프로세스 | ------------------------------------------> | 부모 프로세스 |
+---------------+ +---------------+
| ^
| fork() 에 의해 |
| 자식 프로세스 생성 | exit() 에 의해
v | 실행 프로세스 종료
+---------------+ +-------------------+ |
| 자식 프로세스 | ------------> | 실행 프로세스 대체 | -------'
+---------------+ +-------------------+
exec() 에 의해
실행해야 할 프로세스로 대체
부모 프로세스는 자식 프로세스가
+--------------+ 종료되기까지 Wait 상태 +------------+
--->| bash (1000) | ------------------------------------------> | bash (1000) |
+--------------+ +------------+
| ^
| fork() 에 의해 |
| 자식 프로세스 생성 | exit() 에 의해
v | 실행 프로세스 종료
+-------------+ +-------------------+ |
| bash (2000) | -----------> | 실행 프로세스 대체 | -----------'
+-------------+ +-------------------+
exec() 에 의해
실행해야 할 프로세스로 대체
o 프로세스의 실행 측면의 두가지 가능성
- 부모와 자식이 동시에 실행
- 부모는 자식의 일부 또는 전부가 종료될때까지 wait
o 주소공간의 경우에서의 두가지 가능성
- 자식은 부모의 복사판
- 자식 프로세스는 별도의 프로그램을 적재
o 프로세스의 종료
- exit 명령
자신의 마지막 명령이 수행된 후 운영체제에게 요청하고 자신은 종료
- abort 명령
강제종료, 부모프로세스만이 권한 행사
줄초상 (Xwindows 종료가 되면 Xwindows 에서 실행된 프로세스들 모두 종료)
부모가 종료되면 자식들도 따라서 강제로 종료
ex)
# ./test.sh 1&
# pstree
init-+
| :
| :
|-sshd---sshd---bash-+-pstree
| `-test.sh---sleep
# /etc/init.d/sshd stop
init-+-acpid
| :
| :
|-sshd---bash-+-pstree
| `-test.sh---sleep
o 프로세스의 종류
- 포그라운드 프로세스
사용자와 직접적인 대화를 하고 있는 프로세스 (bash -> top)
쉘에서 어떤 명령어를 실행하면 기본적으로 그 프로세스는
포그라운드 프로세스로 동작한다. (ex 명령어)
- 백그라운드 프로세스
사용자와 직접적인 대화를 하지않고 뒤에서 실행되는 프로세스
데몬, 시스템운영에 필요한 프로세스들
쉘에서 명령어를 실행할때 프그라운드로 동작이 되므로
이를 백그라운드로 바꾸기 위해서는 명령어 뒤에 & 기호를
써주면 백그라운드 프로세스로 동작한다. (ex 명령어&)
- 좀비 프로세스
o 프로세스 전환
- bash 상태에서 기본적으로 실행되는 프로세스는 모두 포그라운드 로 동작한다.
- fg, bg 명령어
백그라운드 프로세스 -> 포그라운드 프로세스 전환
!!! 작업번호를 알아야 한다. (jobs 명령어로 확인)
& -> jobs -> fg %<작업번호>
포그라운드 프로세스 -> 백그라운드 프로세스
!!! 포그라운드 프로세스를 중지하고 백그라운드로 전환한다.
Ctrl + Z -> bg %<작업번호>
o init process
부모프로세스가 죽으면 자식프로세스가 종료되는 경우도 있지만
그렇지 않은경우는 init (/sbin/init) 프로세스가 받아들인다.
o PID
- 실행할때 각 프로세스에게 번호를 부여한다.
ex)
ps -ef | head
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 12:20 ? 00:00:00 init [3]
o login 해서 명령어를 실행시킨 상태
~ init -> login -> bash -> 명령어1 -> 명령어2
# ./test.sh 1&
# pstree
init-+
| :
| :
|-sshd---sshd---bash-+-pstree
| `-test.sh---sleep
# /etc/init.d/sshd stop
init-+-acpid
| :
| :
|-sshd---bash-+-pstree
| `-test.sh---sleep
init 0 <-- 줄초상
o 프로세스 우선순위
- nice : 프로그램 실행시 우선순위를 변경한다.
- renice : 실행되고 있는 프로세스의 우선순위를 변경한다.
<----------+---------->
-19 0 +19
우선순위 : 높다 <-----+------->낮다
ps(stat) < 표시 N 표시
*** 일반유저는 프로세스의 우선순위를 높힐 수 없다. ***
- 쪽으로 못간다. + 갔다가 다시 - 쪽으로 못간다.
우선순위 높다 -> 숫자 작다 -> CPU가 신경 더 많이 쓴다
ex)
su - test
$ sleep 200 &
[1] 837
$ renice -1 837 <-- X
$ renice +1 837 <-- O
$ renice +5 837 <-- O
$ renice +3 837 <-- X
(우선순위가 +5 였는데 +3으로 변경하면 원래의 우선순위에서 -2 만큼 우선순위를 높이는 결과이기 때문에 일반 사용자로는 허가 거부됨)
o 프로세스 관련 명령어
- ps
모든 프로세스를 보여준다. ( BSD계열, SystemV계열)
사용법 :
ps aux
ps -ef
ps 각각의 필드
o kill
프로세스에게 신호(signal)를 보내는 명령어다.
- 프로세스에게 signal 을 주면 default 가 15번 신호를 보내준다.
kill <PID> , kill -15 <PID>, kill -SIGTERM <PID>
# ./test.sh
[1] 12297
# kill 12297
#
[1]+ Terminated ./test.sh
# kill -15 12297
# kill -SIGTERM 12297
- 프로세스에게 강제적으로 signal 을 줘서 프로세스를 종료할때 9번 신호를 사용한다.
kill -9 <PID> , kill -SIGKILL <PID>
# kill -l
==========================================================
LAB> 프로세스에 신호 보내기
# sleep 100 &
# sleep 200 &
# ps aux | grep sleep
root 959 0.0 0.1 4856 472 pts/1 S 13:39 0:00 sleep 100
root 960 0.0 0.1 4856 472 pts/1 S 13:39 0:00 sleep 200
root 971 0.0 0.2 5144 740 pts/1 R+ 13:40 0:00 grep sleep
# kill 959 <-- PID 959 번 에게 15번 신호를 보낸다.
[1]- 종료됨 sleep 100
# kill -9 960
[2]+ Killed sleep 200
==========================================================
# kill -l
15) SIGTERM 종료 <-- 프로그램에서 막을 수 있다.
9) SIGKILL 강제종료 <-- 프로그램에서 못 막는다.
o killall
- 이름으로 프로세스에 신호보내기
# ps
PID TTY TIME CMD
5254 pts/0 00:00:00 su
5255 pts/0 00:00:00 bash
5494 pts/0 00:00:00 test.sh
5500 pts/0 00:00:00 test.sh
5505 pts/0 00:00:00 test.sh
8900 pts/0 00:00:00 sleep
8901 pts/0 00:00:00 sleep
8902 pts/0 00:00:00 sleep
8903 pts/0 00:00:00 ps
# kill 5494
#
[1] Terminated ./test.sh
# kill -15 5500
#
[2]- Terminated ./test.sh
# kill -9 5505
[3]+ Killed ./test.sh
# ps
PID TTY TIME CMD
5254 pts/0 00:00:00 su
5255 pts/0 00:00:00 bash
8975 pts/0 00:00:00 ps
o top
- 실시간으로 프로세스의 상태를 확인
=======================================================
LAB> top 으로 프로세스를 종료
# yes > /dev/null &
[1] 1215
# top
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1215 root 25 0 1756 388 328 R 96.3 0.2 0:06.18 yes
:
:
k ->
PID to kill: 1215
Kill PID 1215 with signal [15]: 9
=======================================================
=======================================================
LAB> top 을 실행하는 사용자 생성하기
- 서버관리할때 참고
# useradd -s /usr/bin/top topuser
# passwd topuser
# ssh topuser@localhost
top 이 실행된다.
=======================================================
=======================================================
LAB> uptime 확인하기
아래 명령어로 확인이 가능하다.
top
uptime
w
=======================================================
============================================================================
실습> 백그라운드 프로세스를 만들어서 실행하기
# vi test.sh
-- test.sh --
#!/bin/sh
while :
do
sleep 1
done
-- test.sh --
# chmod 755 test.sh
# ./test.sh 1 & <-- 백그라운드 프로세스로 실행
[1] 31348
# ./test.sh 2 & <-- 백그라운드 프로세스로 실행
[2] 31351
# ./test.sh 3 & <-- 백그라운드 프로세스로 실행
[3] 31356
# jobs
[1] Running ./test.sh 1 &
[2]- Running ./test.sh 2 &
[3]+ Running ./test.sh 3 &
~~~
작업번호
# fg <-- 백그라운드 -> 포그라운드로 전환 (fg 만 입력하면 + 기호가 있는 작업번호가 동작)
./test.sh 3
^Z <-- Ctrl + Z (중지)
[3]+ Stopped ./test.sh 3
# jobs
[1] Running ./test.sh 1 &
[2]- Running ./test.sh 2 &
[3]+ Stopped ./test.sh 3 <-- 중지된 상태로 출력
# bg %3 <-- 작업번호 3번을 백그라운드로 동작
[3]+ ./test.sh 3 &
# jobs
[1] Running ./test.sh 1 &
[2]- Running ./test.sh 2 &
[3]+ Running ./test.sh 3 &
# fg %1 <-- 작업번호 1번을 포그라운드로 동작
./test.sh 1
^C <-- Ctrl + C (프로세스 중지)
# jobs
[2]- Running ./test.sh 2 &
[3]+ Running ./test.sh 3 &
# kill %2 <-- 작업번호 2번을 신호를 보낸다. (15번 신호)
[2]- Terminated ./test.sh 2
# kill %3 <-- 작업번호 2번을 신호를 보낸다. (15번 신호)
[3]+ Terminated ./test.sh 3
# jobs <-- 3개의 프로세스 모두 종료
============================================================================
=========================================================================
실습> 프로세스의 우선순위를 확인해보자.
# ./test.sh 1 &
[1] 1535
# ./test.sh 2 &
[2] 1574
# ./test.sh 3 &
[3] 1579
# ps aux| grep test.sh
root 1535 0.0 0.1 2520 972 pts/0 S 15:34 0:00 /bin/sh ./test.sh 1
root 1574 0.0 0.1 2520 976 pts/0 S 15:34 0:00 /bin/sh ./test.sh 2
root 1579 0.0 0.1 2520 976 pts/0 S 15:34 0:00 /bin/sh ./test.sh 3
root 1602 0.0 0.0 1956 496 pts/0 R+ 15:34 0:00 grep test.sh
#renice -1 -p 1535
# ps aux| grep test.sh
root 1535 0.0 0.1 2520 976 pts/0 S< 15:34 0:00 /bin/sh ./test.sh 1
root 1574 0.0 0.1 2520 980 pts/0 S 15:34 0:00 /bin/sh ./test.sh 2
root 1579 0.0 0.1 2520 980 pts/0 S 15:34 0:00 /bin/sh ./test.sh 3
root 2167 0.0 0.0 1956 496 pts/0 R+ 15:37 0:00 grep test.sh
# renice -10 -p 1535
1535: old priority -1, new priority -10
# renice -18 -p 1535
1535: old priority -10, new priority -18
# renice -19 -p 1535
1535: old priority -18, new priority -19
# renice -20 -p 1535
1535: old priority -19, new priority -20
# renice -21 -p 1535
1535: old priority -20, new priority -20
# renice 1 -p 1535
1535: old priority -20, new priority 1
# ps aux| grep test.sh
root 1535 0.0 0.1 2520 980 pts/0 SN 15:34 0:00 /bin/sh ./test.sh 1
root 1574 0.0 0.1 2520 984 pts/0 S 15:34 0:00 /bin/sh ./test.sh 2
root 1579 0.0 0.1 2520 984 pts/0 S 15:34 0:00 /bin/sh ./test.sh 3
root 2850 0.0 0.0 1956 496 pts/0 R+ 15:40 0:00 grep test.sh
# renice 100 -p 1535
1535: old priority 1, new priority 19
=========================================================================
=========================================================================
실습> 프로그램 실행시 우선순위를 지정하고 실행하는 방법
# nice -n 3 ./test.sh 4 &
[4] 3526
# ps aux | grep test.sh
root 1535 0.0 0.1 2520 984 pts/0 SN 15:34 0:00 /bin/sh ./test.sh 1
root 1574 0.0 0.1 2520 988 pts/0 S 15:34 0:00 /bin/sh ./test.sh 2
root 1579 0.0 0.1 2520 988 pts/0 S 15:34 0:00 /bin/sh ./test.sh 3
root 3526 0.0 0.1 2520 972 pts/0 SN 15:44 0:00 /bin/sh ./test.sh 4
root 3552 0.0 0.1 1956 524 pts/0 R+ 15:44 0:00 grep test.sh
# nice -n -1 ./test.sh 5 &
[5] 3663
# ps aux | grep test.sh
root 1535 0.0 0.1 2520 984 pts/0 SN 15:34 0:00 /bin/sh ./test.sh 1
root 1574 0.0 0.1 2520 988 pts/0 S 15:34 0:00 /bin/sh ./test.sh 2
root 1579 0.0 0.1 2520 988 pts/0 S 15:34 0:00 /bin/sh ./test.sh 3
root 3526 0.0 0.1 2520 972 pts/0 SN 15:44 0:00 /bin/sh ./test.sh 4
root 3663 0.0 0.1 2520 968 pts/0 S< 15:44 0:00 /bin/sh ./test.sh 5
root 3675 0.0 0.0 1956 496 pts/0 R+ 15:44 0:00 grep test.sh
=========================================================================
=========================================================================
실습> 프로그램을 짤때 15번 신호(signal)을 무시하는 방법
# install /dev/null test.sh
# vi test.sh
-- test.sh --
#!/bin/sh
trap "echo ^^*" SIGTERM
while :
do
sleep 1
done
-- test.sh --
# ./test.sh &
[1] 12357
# kill 12357
^^*
# jobs
[1]+ Running ./test.sh &
#kill 12357
# ^^*
# jobs
[1]+ Running ./test.sh &
# kill -9 12357 <-- 강제종료
=========================================================================
=========================================================================
LAB> SIGNAL 이름을 이용해서 프로세스를 종료시켜보자.
# sleep 100 &
[1] 1004
# sleep 200 &
[2] 1005
# kill -SIGTERM 1004
[1]- Terminated sleep 100
# kill -SIGKILL 1005
[2]+ Killed sleep 200
=========================================================================
=========================================================================
실습> killall 을 이용해서 프로세스의 이름을 종료시켜보자.
# ./test.sh &
[1] 12601
# ./test.sh &
[2] 12603
# ./test.sh &
[3] 12606
# ./test.sh &
[4] 12608
# ./test.sh &
[5] 12612
# jobs
[1] Running ./test.sh &
[2] Running ./test.sh &
[3] Running ./test.sh &
[4]- Running ./test.sh &
[5]+ Running ./test.sh &
# killall -9 test.sh
[1] Killed ./test.sh
[2] Killed ./test.sh
[3] Killed ./test.sh
[4]- Killed ./test.sh
[5]+ Killed ./test.sh
=========================================================================