IT/영어 공부노트

[리눅스] 프로세스 기초(fork(), 프로세스 상태) 본문

💻 IT/linux

[리눅스] 프로세스 기초(fork(), 프로세스 상태)

소저어엉 2024. 6. 8. 17:35
반응형

<그림으로 배우는 리눅스 구조> 책을 읽고 정리한 내용으로, 
개인 공부 목적의 포스팅입니다.

 

~책 보러가기~


ps aux

시스템에 존재하는 모든 프로세스를 확인하는 명령

ps aux --no-header 옵션으로 헤더 출력 제거 가능 (프로세스 개수 조사 가능)

 

 

프로세스 생성

새로운 프로세스를 생성하는 목적은 크게 2가지가 있다. 

  1. 동일한 프로그램 처리를 여러 프로세스에 나눠서 처리하기 - fork()
  2. 다른 프로그램을 생성하기 - fork(), execve()

fork()

fork()는 같은 프로세스를 두 개로 분열시킨다. 이 때 원본 프로세스를 부모 프로세스, 생성된 프로세스를 자식 프로세스라고 한다. 

  1. 부모 프로세스가 fork() 함수를 호출한다. 
  2. 자식 프로세스용 메모리 영역을 확보한 후 그곳에 부모 프로세스의 메모리를 복사한다. 
  3. 부모 프로세스와 자식 프로세스 모두  fork() 함수로 복귀한다. 

execve()

execve()가 동작하려면 실행 파일은 프로그램 코드와 데이터 외에도 아래의 데이터가 필요하다. 

  • 코드 영역의 파일 오프셋, 크기 및 메모리 맵 시작 주소
  • 데이터 영역의 파일 오프셋, 크기 및 메모리 맵 시작 주소
  • 최초로 실행할 명령의 메모리 주소

readelf -S

코드와 데이터의 파일 오프셋, 크기, 시작주소를 확인하는 명령어


프로세스의 부모 자식 관계

컴퓨터 ON 시 시스템은 다음 순서로 초기화된다.

  1. 컴퓨터 전원을 킨다
  2. BIOS나 UEFI 같은 펌웨어를 기동하고 하드웨어를 초기화한다
  3. 펌웨어가 GRUB 같은 부트 로더를 기동한다.
  4. 부트 로더가 OS 커널을 기동한다.
  5. 리눅스 커널이 init 프로세스를 기동한다.
  6. init 프로세스가 자식 프로세스를 기동하고 그 자식 프로세스를 기동하고,, 이어져 프로세스 트리 구조를 만든다. 

pstree

프로세스의 부모 자식 관계를 트리 구조로 표시하는 명령어. -p 옵션을 사용하면 PID도 표시한다. 

결과를 보면, 모든 프로세스는 pid가 1인 init에서 비롯된 것을 알 수 있다. 

 


프로세스 상태 

ps aux

시스템에서 동작하는 프로세스를 기동한 시각 및 사용한 CPU 시간 합계는 위 명령어의 START 필드 및 TIME 필드에서 확인 가능하다. 

위를 보면 CPU를 사용한 시간이 2초 이하로 매우 짧다. 각 프로세스는 실행한 후 어떤 이벤트가 발생할 때까지 CPU를 사용하지 않고 가만히 있는 슬립 상태로 기다리고 있었다. 

 

프로레스 상태는 위 결과에서 STAT 필드에서 알 수 있다. 

  • 첫 글자가 S면 슬립 상태
  • 첫 글자가 R이면 실행 상태
  • 첫 글자가 Z 이면 좀비 상태

 

시스템의 모든 프로세스가 슬립 상태라면, 논리 CPU는 idle 프로세스를 동작시킨다. (이는 ps에서 보이지 않는다.)

논리 CPU를 휴식 상태로 전환하고, 하나 이상의 프로세스가 실행 가능 상태가 될 때까지 소비 전력을 억제하면서 대기한다. 


프로세스 종료

exit_group()

프로세스를 종료하려면 exit_group() 시스템 콜을 호출한다. 이는 exit() 함수를 호출하면 내부에서 시스템콜을 부르는 함수가 호출된다. exit_group()는 함수 내부에서 커널이 메모리 같은 프로세스가 사용한 자원을 회수한다. 

wait(), waitpid()

프로세스가 종료하면 부모 프로세스는 위 시스템 콜을 호출해서 아래의 정보를 얻을 수 있다. 

  • 프로세스 반환값. exit() 인수에 0~255를 지정하면 인수값이 그대로 반환값이 됨
  • 시그널에 따라 종료했는지 여부
  • 종료할 때까지 얼마나 CPU 시간을 사용했는지 정보 

위 정보를 통해 프로세스 반환값에 따라 프로세스의 정상, 비정상 종료 여부를 판정해 에러 로그를 출력하는 후속 처리가 가능하다. 


좀비 프로세스와 고아 프로세스

좀비 프로세스란?

종료했지만 부모가 종료 상태를 확인하지 않은 상태의 프로세스를 말한다. 

 

부모 프로세스는 자식 프로세스 종료 상태를 회수해서 남아 있는 자원을 커널로 돌려줘야 한다. 

 

wait() 계열 시스템 콜을 실행하기 전에 부모 프로세스가 종료되면 해당하는 자식 프로세스는 고아 프로세스가 된다. 커널은 init을 고아 프로세스의 새로운 부모로 지정한다. init은 정기적으로 wait() 계열 시스템콜을 호출해서 시트템 자원을 회수한다 .


시그널

시그널은 어떤 프로세스가 다른 프로세스에 어떤 신호를 보내서 외부에서 실행 순서를 강제적으로 바꾸는 방법이다. 주로 SIGINT를 자주 사용한다. 

 

SIGCHLD : 자식 프로세스 종료 시 부모 프로세스에 보내는 시그널. 

SIGSTOP : 프로세스 실행을 일시적으로 정지한다. (Ctrl+Z)

SIGCONT : SIGSTOP 등으로 정지한 프로세스를 재개한다. 

 

man 7 signal

시그널 목록을 확인할 수 있다. 

반응형