컴퓨터 구조 + 운영체제(OS)

[Linux] 시스템 프로세스란?

Jay_J 2024. 2. 5. 14:34

※프로세스(process)란?

  • 컴퓨터의 하드디스크에 존재하는 프로그램이 메모리 영역에 상주하며 실행되는것
  • 각 프로세스는 고유한 자신만의 아이디(PID)를 가지며, 

즉, 우리가 실행하는 모든 프로그램이 전부 다 하나의프로세스이다. 작업 관리자를 켜보면 '프로세스' 라는 탭이 있는데 거길 보면 수많은 프로세스들이 실행중인것을 볼 수 있다.

 

※프로세스 생성 절차

더보기
리눅스의 프로세스 생성 절차를 간단히 나타낸 그림
  • 뗏목 : 부모 프로세스
    • 부모 프로세스는 여러개의 자식 프로세스들을 복제할 수 있으며 이러한 자식 프로세스들을 통해 다수의 작은 작업들을 동시에 처리하도록 한다.
    • 모든 프로세스는 혼자서 실행 될 수 없으며 부모 프로세스에 종속되어 사용된다.
    • 부모 프로세스가 작업을 종료하면, 그 하위에 있는 자식 프로세스들도 강제 종료된다.
  • 고무보트 : 자식 프로세스
    • fork()를 통해 자식 프로세스가 생성(spawn)되고, 자식 프로세스는 exec호출을 통해 다른 프로세스를 실행하고, 새로운 프로세스로 자신을 대체할 수 있다.
  • 유리병 : exit()의 결괏값

위 그림을 보면서 이해하면 이해하기 쉬울것이다. 먼저, 부모 프로세스는 fork()명령어를 통해 자기 자신을 복제한다. 그렇게 되면 자식 프로세스가 생성되는데, 이 자식 프로세스는 부모 프로세스의 속성들을 상속받았다. 그런데 여기서 의문이 들것이다. 이미 부모 프로세스가 일을 하고있는데 왜 굳이 자신의 복제본인 자식 프로세스를 생성하지? 

 

자식 프로세스에게 부모 프로세스의 일이 아닌 자식 프로세스만의 일을 시키고 싶다면 exec() 커맨드를 통해 다른 프로세스를 실행 시킬 수 있다. 그동안, 부모 프로세스는 자식 프로세스의 일이 끝날때까지 기다린다.  그 다음, exit()을 통해 자식 프로세스가 종료되고, 정상적으로 종료되었다면 0을 반환한다. 이 상황에서 부모 프로세스는 wait()을 통해 자식 프로세스의 일이 잘 처리되었는지 확인하고, 그 다음에 부모 프로세스의 프로세스가 진행된다.

 

한마디로 줄여보면, 부모 프로세스는 fork후 자식 프로세스의 동작 완료까지 대기하고, 자식 프로세스는 동작 완료 후 부모 프로세스에게 동작이 끝났다는걸 알려야 한다.

 

 

※포그라운드, 백그라운드 프로세스란?

  • 포그라운드 프로세스(fg)
    • 실행화면에 나타나 사용자와 상호작용 하는 프로세스
    • 취소하고 싶을땐 Ctrl + C를 통해 프로세스를 종료한다.
    • shell 상태에서 명령을 내리면 사용자는 해당 프로세스가 종료 될때까지 기다려야함
    • 신호 송/수신 가능
  • 백그라운드 프로세스(bg)
    • 실행중이지만, 화면에 나타나지 않고, 저 뒤 어딘가에서 실행중인 프로세스
    • 커맨드 뒤에 &를 붙여 동작시키며, 명령을 내린 사용자는 자신이 하고자 하는 명령어를 실행 시킬 수 있음
  • 프로세스 변경 방식
    • fg를 bg로 보내고 싶을때 : ctrl + z로 잠시 작업을 멈춘다음 '#bg'로 다시 백그라운드로 보낼 수 있음.
    • bg를 fg로 보내고 싶을때 :  (fg % [작업번호])

 

※SIGNAL(신호) 란?

  • 시그널이란 프로세스에서 일어나는 비동기적인 사건.
  • 어느 시점에서 이벤트가 발생할지 예측불가
  • 시그널이 전달되는 방식은 다음과 같다 : '시그널 발생' -> '프로세스' -> '동작을 취함'

조금 더 자세하게 표현하자면,

1. main 프로그램 실행중 시그널이 발생했다. 

2. 이 시그널을 signal handler에게 보낸다. 

3. signal handler가 이 시그널을 처리한다.

4. 시그널이 맨 처음 발생한곳으로 돌아간다.

5. 시그널 처리 후 프로그램 명령어를 다시 수행한다.

 

여기서 가장 많이 쓰이는 커맨드가 kill이다. kill은 프로세스에게 지정된 시그널을 보내준다. 그렇지만 kill 명령어를 사용하기 위해서는 PID를 알아야 한다. 그래야 어떤 프로세스에게 어떤 시그널을 보낼지 알 수 있으니까!

 

아래는 기본적인 명령어들이다

  • ps : 현재 실행중인 프로세스 목록을 확인한다. 여기서 PID를 찾은 후 kill 명령어를 써보자

기본적인 kill 명령어는 아래와 같다.

kill[option] PID

 

kill 명령어는 다양한 옵션을 사용할 수 있다.

 

  • -s <signal>: 특정 시그널(signal)을 사용하여 프로세스를 종료한다. 기본적으로 SIGTERM 시그널이 사용된다.
  • -l, --list: 지원되는 시그널(signal) 목록을 출력한다.
  • -a, --all: 현재 사용자에 속한 모든 프로세스를 종료한다.
  • -q, --queue: 프로세스에 시그널을 보내는 대신 시그널을 대기열에 추가한다.

 다양한 시그널들 중에 아래는 자주 쓰이는 대표적인 시그널들이다.

  1. SIGINT : 프로그램 실행 도중 Ctrl+C를 누르면 발생한다. 키보드로부터 명시적으로 발생시키는 시그널이다. SIGINT가 발생한 경우 기본적으로 프로세스가 종료된다.
  2. SIGKILL : 프로세스를 강제로 종료시키는 시그널이다.
  3. SIGSTOP : 프로그램 실행 도중 Ctrl+Z를 누르면 발생한다. 터미널에서 입력된 정지 시그널이다. 
  4. SIGCHILD : 자식 프로세스가 중지되거나 종료되었을 때 부모 프로세스에 전달되는 시그널.
  5. SIGTERM : 가능한 정상 종료를 시키는 시그널이다. 
  6. SIGSEGV : 메모리 참조가 잘못되었을 경우 발생한다.
  7. SIGQUIT : 프로그램 실행 도중 Ctrl+\을 누르면 발생한다. 프로세스를 종료시킨 뒤 core dump를 수행한다.

 위의 시그널들 중 핸들링이 안되는 시그널은 SIGKILL SIGSTOP이다. 그리고 SIGSTOP로 중지시켰던 프로세스를 SIGCONT로 다시 원상복귀 시키면 터미널에서 제어권이 없어져서 Ctrl+C로 안죽는다. 이때는 SIGKILL(9)로 죽여야한다!

 

 

 

출처: https://hasumang.tistory.com/11 [하서망 블로그:티스토리]