##############

## 프로세스 ##

## 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



=========================================================================