본문 바로가기

Tools and Utilities/Linux

[Linux 실습] Ch9. 프로세스 상태 및 메모리와 프로세서(Process Status, Memory and Processor)

오픈 소스 비영리 기관 'Open Source Initiative'의 로고. https://opensource.org/

본 글은 학교 '오픈소스 소프트웨어 입문' 과목을 수강하며 실습(또는 공부)한 내용을 정리한 글입니다.

개인 기록 용도로 작성한 글이라, 직접 이 글을 보고 실습을 따라하기엔 어려움이 많을 것으로 예상됩니다.
혹시 본 글을 보며 Linux를 공부하실 목적이라면, 일단 키워드 위주로 AI에게 물어봐가면서, 본인의 Linux 터미널에서 직접 타이핑해가며 공부하시기를 추천드립니다.

질문이나 의견이 있다면 자유롭게 댓글 달아주세요!


우리는 리눅스 커널 그 사진에서,
I/O Subsystem에서 
터미널과 파일 시스템을 배웠음.
가운데에 커널은 컴네에서 배웠고. 아님 네소설.

그리고 다른 두 개의 subsystem이 있잖음.
프로세스 매니지먼트 서브시스템은, CPU가 CPU를 
어떻게 관리해야 할지에 관한 것.
(프로세서(CPU)에서 돌고 있는 작업들을 프로세스라 부름)
그리고 나머지 메모리 매니지먼트 서브시스템이 있음.
근데 리눅스에서 메모리 관리 명령어가 많지 않음.
지금 프로세스가 사용중인 메모리가 얼마냐? 이런 건 있지만,
다른 애가 메모리를 많이 쓴다고 해서 그 메모리를 뺏어오는 명령어는 없음.
대신, 그렇게 하고 싶으면 그 프로세스 관리 명령어 kill로
그 메모리 많이 쓰는 프로세스를 종료시켜야 함.
그러면 메모리가 돌아옴.


## Process Status
아까 그 프로세스 매니지먼트 서브시스템 관련된 명령어 배우는 느낌.
다음 챕터는 메모리 매니지먼트 시스템.

프로세스 상태는 3가지 정도임.
Run, killed, Suspend(Stop)

run은 실행 중인 상태.
우리가 killed 상태인 프로세스를 보기는 어려움.
왜냐면 kill되면 아주 작은 시간동안만 killed 상태로 존재하고 사라져버림.
suspend는 잠깐 중단시키는 거.


sleep 3 
-> 3초동안 아무것도 안합니다.

sleep 10000 ; tar 하면 
대략 3시간 뒤에 백업을 받음.
리눅스에서 세미콜론(;)은 여러 
명령어를 한 줄에서 순차적으로 실행할 때 사용됨.
cmd1; cmd2 -> cmd1 실행 후 성공/실패와 상관없이 cmd2 실행
cmd1 && cmd2 -> cmd1이 성공하면 cmd2 실행
cmd1 || cmd2 -> cmd1이 실패하면 cmd2 실행

run status는 foreground, background 두 가지 상태가 있음.
foreground로 실행되는 프로세스는 kill -9 시그널을 보내면 종료됨.
이 시그널을 보내는 방법은, ctrl c를 누르면 됨.
ctrl c는 현재 실행중인 foreground 프로세스를 종료시키는 거임.

sleep 2000
-> 지금 이 sleep 2000이라는 프로세스는,
foreground로 실행중이기에 ctrl c로 종료시킬 수 있음.

sleep 2000 & 하면 백그라운드로 실행중.
[1] 1847383가 출력됨
[1] → Job ID (백그라운드 작업 번호)
1847383 → PID (프로세스 ID)
jobs 명령어로 현재 실행중인 잡 목록 볼 수도 있음.

&는 명령어를 백그라운드에서 실행하도록 만드는 기호임.
그럼 우린 ps 입력해서 실행중인 프로세스 목록을 볼 수 있음.
ps
    PID TTY          TIME CMD
1797416 pts/74   00:00:00 bash
1847383 pts/74   00:00:00 sleep
1847448 pts/74   00:00:00 ps

그럼, 저거 죽이고 싶은데 어뜨카냐??
-> kill -9로 직접 죽여주면 됨.
kill -9 1847383
[1]+  Killed                  sleep 2000
그럼 죽었다고 나옴.
또는 kill -9 %1로 Job ID로도 종료할 수 있음.

교수님 꺼 프로세스는 못 죽임. 
모든 건 파일이기에, 우리에겐 죽일 권한이 없음.
그 프로세스의 유저나 그룹이 아니면 못 죽임.
$ps -o user,group,pid,comm로 유저, 그룹 확인 가능.

sleep 2000 & 해서 백그라운드로 도는 거,
어케 포그라운드로 바꾸지??

fg 입력하면 포그라운드로 바꿔짐.
그러면, 우리는 sleep로 기다리는 중이잖음?
이 때 ctrl z를 입력하면,
1 2 3... 하고 시간을 재다가 더 이상 안 셈. 그게 suspend(stop)
    PID TTY          TIME CMD
1797416 pts/74   00:00:00 bash
1849117 pts/74   00:00:00 sleep
1849273 pts/74   00:00:00 ps
보면, killed된 게 아니라, 그냥 suspend 상태로 프로세스가 넘어간 거임.
[1]+  Stopped                 sleep 10
jobs로 확인하면 위처럼 상태가 나옴.

그럼 이거 다시 실행하고 싶으면??
bg 입력하면 됨.fg나.
bg 입력하면 중단됐던 게 백그라운드에서 다시 실행되는 거고,
fg 입력하면 중단됐던 게 포그라운드에서 다시 실행되는 거고.
bg 입력한 다음 fg 입력할 수도 있겠고.

--- 250401 수업

'프로세스'는, '프로세서(CPU)'에서 돌아가는 작업을 논리적인 이름으로 부른 것.
이러한 프로세스는 리눅스에서는 다른 이름으로 '작업(job)'이라고도 불림.
프로세스의 상태는 크게 3가지가 있다. run, killed, stopped.
killed는 몇 나노세컨드동안 이 상태다가 삭제되므로 보기 힘듦.
sleep 10 & 이런 거. 은근 쓸 데 많다!! 10초 뒤에 내가 뭘 하고 싶을 때.
근데 여기서 ctrl z 눌러서 stopped시키면 타이머가 멈춤.
다시 fg든 bg 쳐서 run시키면 타이머 돌다가,
0초 되면 killed로 가겠지.

fg는 다른 작업을 안 하고 얘만 실행하는 거고,
bg는 다른 작업들과 같이 백그라운드에서 실행되는 것.

우리가 a.out을 실행시키면, run상태로 들어감.
프로그램 실행시킬 때, 커맨드 입력하면 되는데,
그냥 치면 포그라운드 상태로 run이 되고,
&을 뒤에 같이 치면 백그라운드 상태로 run이 됨.

포그라운드상태로 실행되고 있는 프로그램을
kill시키고 싶다 -> ctrl c
stop시키고 싶다 -> ctrl z 
(또는 kill 이라고 하는데, kill로도 stop이 되나? 일단 실습하겠다곤 함.)

-> ㅇㅇ. kill은 이론적으론 시그널(signal)을 보내는 명령임.
-9(SIGKILL) 시그널을 보내면 바로 죽이는 거지만,
-STOP(19), -CONT(18)와 같은 시그널을 보내면 stop시키고 다시 run시킬 수 있음.
kill -STOP는 ctrl z, CONT는 bg와 비슷한 효과.
(물론 ctrl z는 포그라운드 프로세스만 stop시킴.)
(또한 포그라운드 프로세스가 돌아가고 있으면 kill -STOP 입력 자체를 못 함.)

그냥 kill만 하면 -15(SIGTERM) 시그널을 보냄. -TERM. 
이건 프로세스를 강제로 끝내는 게 아닌, 프로세스가 정상적으로 종료할 수 있는 기회를 줌.

--- 250401 실습
우리가 ps 하면, ps가 bash랑 ps 떠 있음.
bash는 우리가 쓰고 있는 쉘이고, ps는 ps 내가 쳤으니까.
ps는 '내 터미널에서 실행되고 있는 프로세스들'만 출력됨.
근데, 이 시스템에서 실행되고 있는 모든 프로세스 출력하고픔
-> ps -e하면 됨. 프로세스 겁나 많이 뜸.

ps -el하면 더 상세히 나오는데,
뒤에서 두 번째 숫자는 그 프로세스가 CPU를 얼마나 썼냐 하는 거임.

ps -a 하면 숨겨진 것까지 나옴.
일단 ps -l 해서 자세하게 보자.
F S   UID     PID    PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 S  3110   31120   31119  0  80   0 -  2232 do_wai pts/0    00:00:00 bash
0 S  3110   40924   31120  0  80   0 -  1369 ia32_s pts/0    00:00:00 sleep
0 R  3110   43147   31120  0  80   0 -  2202 -      pts/0    00:00:00 ps

설명)
UID: 이 프로세스의 소유자의 ID(즉, UID)는 뭐냐? 하는 거. 지금 나 foss110의 UID는 3110.
PID: 이 프로세스의 ID.
PPID: 이 프로세스의 부모 프로세스의 ID.
-> 보면 sleep와 ps의 부모 프로세스가 bash인 걸 알 수 있음.
TTY: 저 터미널에서 입력을 기다리고 있다. tty 입력 결과와 같음.

우리 이 시스템에 저렇게 프로세스가 어마무시하게 많은 걸 봤잖음.
리눅스는 멀티 유저 타임 쉐어링 OS란 말임.
뭐 CPU 개수가 1개라고 하면, 엄청 빠르게 번갈아가며 처리해줘야 할 거임.
근데 유사RR 방식들로 하는데, 어떤 프로세스가 다른 프로세스보다 더 중요할 수 있잖음?
그러면 그 프로세스(작업)에 우선순위를 높게 지정해 줘야함.
그런 역할을 하는게 명령어 renice 

참고) 
리눅스는 MLFQ가 아님. CFS인데, 하나의 런큐에서 weight로 직접 CPU 사용 시간 비율 할당해줌.
nice와 renice로 프로세스에게 우선순위(또는 가중치 weight)를 직접 설정해줄 수 있는데,
nice는 프로세스 시작할 때, renice는 실행 중인 프로세스 중간에 우선순위 변경할 때 사용함.

우리는 지금 nice는 쓸 수 없고, renice만 쓸 수 있음.
nice는 슈퍼 유저만 쓸 수 있음.
우선순위를 높이는 데는 renice, 낮추는 데는 nice를 씀.
내가 어떤 계산량이 많은 프로세스를 퇴근하면서 우선순위 낮추고 퇴근하고 싶으면, 
nice 명령어 쓰면 그 프로세스를 가장 낮은 우선순위로 실행시켜 줌.



우리가 sleep 1000한 거 fg bg한 거 기억날거임.
그 다음에, 백그라운드로 돌릴 거면 sleep 1000 &
&는 리다이렉션때 쓰지 않았냐? -> &의 역할이 그것도 있고 이것도 있는 거임.
그렇게 하고 ps 돌리면? -> ps 결과에 나옴.
그러면 sleep 1100 & 하고, sleep 1200 & 한 뒤에 ps 하면?
-> sleep이 3개 나옴.

F S   UID     PID    PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 S  3110   31120   31119  0  80   0 -  2232 do_wai pts/0    00:00:00 bash
0 S  3110   49558   31120  0  80   0 -  1369 hrtime pts/0    00:00:00 sleep
0 S  3110   49576   31120  0  80   0 -  1369 hrtime pts/0    00:00:00 sleep
0 S  3110   49590   31120  0  80   0 -  1369 hrtime pts/0    00:00:00 sleep
0 R  3110   49616   31120  0  80   0 -  2202 -      pts/0    00:00:00 ps

우리가 백그라운드로 실행시켰을 때 나오는 두 숫자는 job number와 PID임.
jobs -l하면 저 두개가 같이 나옴.
[1]  49558 Running                 sleep 1000 &
[2]- 49576 Running                 sleep 1100 &
[3]+ 49590 Running                 sleep 1200 &
여기에 kill -9 49558 하면 해당 프로세스가 kill됨.
foss110@ajousw:~/lab0401$ jobs
[1]   Killed                  sleep 1000
[2]-  Running                 sleep 1100 &
[3]+  Running                 sleep 1200 &
foss110@ajousw:~/lab0401$ jobs
[2]-  Running                 sleep 1100 &
[3]+  Running                 sleep 1200 &

만약 kill명령어가 뭐하는 명령어냐 물어보면,
"네! 프로세스를 죽이는 명령어입니다!" -> 하면 틀림. 
메뉴얼에 나온 대로, "kill은 프로세스에 시그널을 전송하는 명령어입니다."라고 말해야 함.

메뉴얼 보면, -9 == KILL == SIGKILL임. 다 같은 인자.
kill -9 -l -> kill 가능한 모든 프로세스를 kill함.
kill -l [number] -> number에 해당하는 signal name을 알려줌.
kill -l -> 모든 kill 시그널 리스트를 알려줌.

kill -1: SIGHUP: 내가 1번 시그널을 받으면 아 뭔가 바뀌었으니 다시 로딩해야겠다.
하는 역할. 그건 물론 프로그래머가 짜야 함.
예를 들어, 웹서버가 이미 돌고 있는데, 아파치 config 설정 파일을 수정했으면,
이걸 다시 읽게 하려면 웹 서버를 kill시켰다가 다시 실행시켜야 하는데, 이건 디스크도
읽어야 하고 비용이 많이 듦. 그래서 1번 시그널 내가 받으면, config 파일 다시 읽어서
restart할게. 이게 1번. (restart가 더 비용 덜 든다는 듯)

kill -9: SIGKILL는 죽이는 거.
kill -19: SIGSTOP
kill -18: SIGCONT
kill -15: SIGTERM
이 정도는 알아 두자.

-10(SIGUSR1), -12(SIGUSR2)와 같은 시그널은 우리같은 유저가 프로그램 만들 때 쓸 수 있음.
-11(SEGSEGV)는, segmentation violation(세그멘테이션 바이올레이션): 네가 건드리면
안되는 메모리 주소를 건드렸다는 에러 메시지. 이건 즉 런타임에 발생하는 에러 메시지임. 
세그멘테이션 폴트를 말하는 거임.


백그 작업을 포그로 돌릴 때, 백그에 돌아가고 있는 게 2개면 어떻게 구별해요?
-> pid를 쓰거나, job id를 쓰면 됨.
fg %2 이런 식으로.
그리고 ctrl z로 stop시킨 다음에 걔를 다시 백그로 실행시킬거면, 
bg %2 또는 kill -18 %2

그리고, jobs 명시 없이 fg bg 쓰면, 가장 최근에 생성된? 프로세스를 대상으로 수행함.


killall 한 다음에 어떤 문자열을 쓰면,
그 문자열에 해당하는 게 들어있는 모든 프로세스를 다 죽임. 
killall sleep 하면, 다른 모든 유저들것까지 다 죽이려 시도했다가 권한 거부당함.
foss110@ajousw:~/lab0401$ killall sleep
sleep(48941): Operation not permitted
sleep(527444): Operation not permitted
sleep(527516): Operation not permitted
sleep(531122): Operation not permitted
[2]   Terminated              sleep 1100
[3]   Terminated              sleep 1200
[4]   Terminated              sleep 1000
[5]   Terminated              sleep 1300
[6]-  Terminated              sleep 1400
[7]+  Terminated              sleep 1500


만약 우리가 kill -9 -l하면, 우리가 kill 가능한 모든 프로세스를 kill한다고 했잖음??
그러면 bash 즉 쉘 또한 kill됨. 따라서 로그인이 끊김.

--- 이제 기타 등등의 명령어들 배울 거.
bash, source, ( ) 명령어는 다음에 배울 거.

free는 이 시스템에 메모리 공간이 얼마나 남아있는지 알려줌.
              total        used        free      shared  buff/cache   available
Mem:       15822320    13922744      283240      512248     1616336     1042436
Swap:       4194300     1743608     2450692

sensors는 이 컴퓨터에 들어가 있는 코어의 온도들을 보여줌.
bnxt_en-pci-8a00
Adapter: PCI adapter
temp1:        +49.0°C

coretemp-isa-0000
Adapter: ISA adapter
Package id 0:  +63.0°C  (high = +81.0°C, crit = +91.0°C)
Core 0:        +61.0°C  (high = +81.0°C, crit = +91.0°C)
Core 1:        +61.0°C  (high = +81.0°C, crit = +91.0°C)
Core 2:        +62.0°C  (high = +81.0°C, crit = +91.0°C)
Core 3:        +60.0°C  (high = +81.0°C, crit = +91.0°C)
Core 4:        +63.0°C  (high = +81.0°C, crit = +91.0°C)
Core 5:        +61.0°C  (high = +81.0°C, crit = +91.0°C)
Core 6:        +60.0°C  (high = +81.0°C, crit = +91.0°C)
Core 7:        +59.0°C  (high = +81.0°C, crit = +91.0°C)

bnxt_en-pci-8a01
Adapter: PCI adapter
temp1:        +49.0°C

저 high보다 높으면 높은 거고 crit보다 넘으면 셧다운 시켜버림.
이거 서버 CPU임.


w를 치면 로그인해 있는 유저들이 지금 뭘 하고 있는지 정보가 보임.
 06:02:34 up 41 days, 11:04,  3 users,  load average: 0.03, 0.08, 0.11
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
foss110  pts/0    121.169.44.124   04:48    2.00s  0.05s  0.00s w
foss141  pts/132  175.195.197.187  01Apr25  6days  0.04s  0.04s -bash

여기에 다른 유저가 포그라운드로 돌리고 있는 프로세스도 나옴.
얘를 들어, 누가 포그라운드로 sleep 돌리고 있으면, 다른 사람 터미널에선 그것도 나옴.

그리고 맨 윗줄엔 전체적인 상태도 나옴. 서버 CPU. 유저 수 나오고.
load average는 단위 시간 당 얼마나의 작업이 처리되고 있냐는 건데, 뭐 교수님도 어케 보는지 모르겠다 함.