[운영체제] 프로세스와 스레드

Doyeon Lim·2022년 2월 3일
0

운영체제

목록 보기
3/3
post-thumbnail
post-custom-banner

> Tech-I-Learned Github 바로가기

쉽게 배우는 운영체제를 읽고 스스로 이해하기 위해 정리한 내용입니다.

📗 프로세스

운영체제에서 프로세스는 하나의 작업 단위로 태스크 task라고도 부른다.
프로그램은 저장장치에 저장되어 있는 정적인 상태이고, 프로세스는 실행을 위해 메모리에 올라온 동적인 상태이다.

✅프로세스 제어 블록 PCB

프로세스 제어 블록 PCB Process Control Block에는 프로세스를 처리하는데 필요한 다양한 정보가 들어 있으며 TCB Task Control Block 라고도 한다. PCB가 없으면 프로그램이 프로세스로 전환되지 못한다. PCB는 프로세스 생성 시 만들어져서 프로세스가 실행을 완료하면 폐기된다.

PCB는 운영체제가 해당 프로세스를 위해 관리하는 데이터 구조이기 때문에 운영체제 영역에 만들어진다.

PCB의 구성 요소는 다음과 같다.

[PCB 구성 요소]
1. 포인터

  • PCB의 첫 번째 블록에는 포인터가 저장된다. 준비 상태나 대기 상태의 큐를 구현할 때 사용한다.

2. 프로세스 상태

  • 생성, 준비, 실행, 대기, 보류 준비, 보류 대기 등의 프로세스 상태는 저장한다.

3. 프로세스 구분자 PID

  • 운영체제 내의 여러 프로세스를 구별하기 위한 구분자를 저장한다.

4. 프로그램 카운터

  • 다음에 실행될 명령어의 위치를 가리키는 프로그램 카운터의 값을 저장한다.

5. 프로그램 우선순위

  • 프로세스 중요도에 따른 우선순위를 저장한다. 사용자 프로세스보다 중요도가 큰 커널 프로세스는 우선순위가 높고, 사용자 프로세스끼리도 우선순위가 다르다.

6. 레지스터 정보

  • 프로세스 실행 중에 사용하던 레지스터(accumulator, index register, stack pointer 등)의 값이 저장된다.

7. 메모리 관리 정보

  • 프로세스가 메모리의 어디에 있는지 나타내는 메모리 위치 정보, 메모리 보호를 위해 사용하는 경계 레지스터 값과 한계 레지스터 값 등이 저장된다. segmentation table, page table 등의 정보도 보관한다.

8. 할당된 자원 정보

  • 프로세스 실행을 위해 사용하는 입출력 자원이나 오픈 파일 등에 대한 정보를 저장한다.

9. 계정 정보

  • 계정 번호, CPU 할당 시간, CPU 사용 시간 등을 저장한다.

10. PPID, CPID

  • 부모 프로세스를 가리키는 PPID와 자식 프로세스를 가리키는 CPID 정보를 저장한다.

✅프로세스 상태

운영체제에서 여러 가지 이유로 프로세스 상태가 변화한다.
일괄 작업 시스템의 경우 프로세스가 생성된 후 CPU를 얻어 실행되고 작업을 마치면 종료된다.
따라서 일괄 작업 시스템의 프로세스 상태는 생성, 실행, 완료이다.

시분할 시스템에서는 CPU를 다른 프로세스에 넘겨주는 일이 빈번하기 때문에 일괄 작업 시스템보다 프로세스 상태가 복잡하다.

프로세스의 4가지 상태

  • 생성 상태 create status : 프로세스가 메모리에 올라와 실행 준비를 완료한 상태, PCB가 생성
  • 준비 상태 ready status : 생성된 프로세스가 CPU를 얻을 때까지 기다리는 상태
    • 준비 상태의 여러 프로세스 중 다음에 실행할 프로세스를 선정하는 일은 CPU 스케줄러가 담당
    • 디스패치 dispatch : 준비 -> 실행 상태로 바꾸는 CPU 스케줄러의 작업
    • 타임 아웃 time out : 프로세스에 배당된 작업 시간인 타임 슬라이스(타임 퀀텀) 내에 작업을 끝내지 못해 다시 준비 상태로 돌아가는 것 -> 클록으로부터의 인터럽트
  • 실행 상태 running status : 준비 상태에 있는 프로세스 중 하나가 CPU를 얻어 실제 작업을 수행하는 상태, 주어진 시간 내에 작업을 끝내지 못하면 준비 상태로 돌아감
  • 완료 상태 terminate status : 실행 상태의 프로세스가 주어진 시간 내에 작업을 마치면 완료 상태로 진입, PCB가 사라진 상태

프로세스의 5가지 상태

오늘날 운영체제 효율성을 고려해 프로세스의 상태를 대기 상태를 포함한 5가지로 표현할 수 있다.

  • 생성 상태 create status : OS로부터 PCB를 할당 받은 상태
  • 준비 상태 ready status : PCB는 준비 큐에서 기다리며 CPU 스케줄러에 의해 관리
  • 실행 상태 running status : 프로세스가 CPU를 할당받아 실행되는 상태, 타임 슬라이스 동안 작업
  • 대기 상태 blocking status : 실행 상태에 있는 프로세스가 입출력을 요청하면 입출력이 완료될 때까지 기다리는 상태, 입출력장치별로 마련된 큐에서 대기
  • 완료 상태 terminate status : 프로세스가 종료되는 상태, 코드와 데이터를 메모리에서 삭제하고 PCB를 폐기
    - 코어 덤프 core dump : 비정상적으로 종료되는 강제 종료를 만나면 디버깅하기 위해 강제 종료 직전의 메모리 상태를 저장장치로 옮기는 것

휴식 상태와 보류 상태

생성, 준비, 실행, 대기, 완료 상태를 활성 상태 active status 라고 한다. 이외에도 특별한 상태가 있다.

  • 휴식 상태 pause status : 프로세스가 작업을 일시적으로 쉬고 있는 상태
  • 보류 상태 suspend status : 프로세스가 메모리에서 잠시 쫓겨난 상태
    • 메모리가 꽉 차서 일부 프로세스를 메모리 밖으로 내보낼 때
    • 프로그램에 오류가 있어서 실행을 미루어야 할 때
    • 바이러스와 같이 악의적인 공격을 하는 프로세스라고 판단될 때
    • 매우 긴 주기로 반복되는 프로세스라 메모리 밖으로 쫓아내도 큰 문제가 없을 때
    • 입출력을 기다리는 프로세스의 입출력이 계속 지연될 때

보류 상태에 들어간 프로세스는 메모리 밖으로 쫓겨나 스왑 영역 swap area에 보관된다.

✅context switching

context switching은 CPU를 차지하던 프로세스가 나가고 새로운 프로세스를 받아들이는 작업을 말한다. 이때 두 PCB의 내용이 변경된다.

일반적으로 한 프로세스가 자신에게 주어진 시간을 다 사용하면 발생하고, 인터럽트가 걸렸을 때도 발생한다.

✅프로세스의 구조

프로세스는 정적 할당 영역인 코드 영역, 데이터 영역과 동적 할당 영역인 힙 영역, 스택 영역으로 구성된다.

  • 코드 영역 code area : 프로그램 본문이 기술된 곳, 읽기 전용으로 처리됨
  • 데이터 영역 data area : 변수나 파일 등의 각종 데이터를 모은 곳, 상수는 읽기 전용이지만 대부분의 변수는 읽기와 쓰기가 가능
  • 스택 영역 stack area : 운영체제가 프로세스를 실행하기 위해 부수적으로 필요한 데이터를 모아놓은 곳, 사용자에게 보이지 않음
    • 함수 호출 시 되돌아올 메모리 주소를 저장하거나 변수 사용범위에 영향을 미치는 scope를 구현할 때 사용
  • 힙 영역 heap area : 동적으로 할당되는 변수 영역

프로세스의 생성과 복사

사용자가 프로그램을 실행하면 운영체제는 프로그램을 메모리로 가져와 코드 영역에 넣고 PCB를 생성한다. 그리고 메모리에 데이터 영역과 스택 영역을 확보한 후 프로세스를 실행한다.

fork() 시스템 호출을 통해 실행 중인 프로세스로부터 새로운 프로세스를 복사하는 방법도 있다.

기존의 프로세스는 부모 프로세스가 되고 새로운 프로세스는 자식 프로세스가 되며 부모-자식 관계로 연결된다.

[fork() 시스템 호출 동작 과정]

  • PID가 변경된다.
  • 각 프로세스가 차지하고 있는 메모리 위치가 다르므로 메모리 관련 정보가 바뀐다.
  • PPID와 CPID가 바뀐다. 자식 프로세스는 자식 프로세스가 없으므로 CPID의 값이 -1이다.

[fork() 시스템 호출의 장점]

  • 프로세스 생성 속도가 빠르다.
  • 추가 작업 없이 자원을 상속할 수 잇따.
  • 시스템 관리를 효율적으로 할 수 있다.

프로세스의 전환

exec() 시스템 호출을 통해 기존의 프로세스를 새로운 프로세스로 전환할 수 있다. 프로세스는 그대로 둔 채 내용만 바꾼다.

exec() 시스템 호출의 사용 목적은 프로세스의 구조체를 재활용하기 위함이다. 새로운 프로세스를 만들기 위해서는 PCB를 만들고 메모리 자리를 확보해하며, garbage collection을 위해 상위 프로세스와 부모-자식 관계를 만들어야 한다. 이때 exec() 시스템 호출을 사용하면 그대로 사용할 수 있어 편리하다.

[exec() 시스템 호출 동작 과정]

  • 코드 영역의 내용을 지우고 새로운 코드로 변경한다.
  • 데이터 영역이 새로운 변수로 채워지고 스택 영역이 리셋된다.
  • PCB의 PID, PPID, CPID, 메모리 관련 사항 등은 변하지 않지만 프로그램 카운터 레지스터 값을 비롯한 각종 레지스터와 사용한 파일 정보가 모두 리셋된다.

✅프로세스 계층 구조

프로세스 계층 구조는 동시에 여러 작업을 처리하고 종료된 프로세스의 자원을 회수하는데 유용하다.

  • 여러 작업의 동시 처리 : fork() 시스템 호출로 프로세스를 여러 개 만들어서 동시에 처리할 수 있도록 한다.
  • 용이한 자원 회수 : 프로세스 간의 책임 관계가 분명해져 시스템을 관리하기 수월하다.

zombie process

부모 프로세스가 먼저 종료되거나 자식 프로세스가 비정상적으로 종료되어 부모 프로세스에 연락이 안되는 경우가 발생해, 자식 프로세스가 종료되지 않거나, 사용하던 자원이 그대로 남게 되는 경우가 있다.

이 때, 비정상적으로 남아있는 프로세스를 orphan process, zombie process라고 한다.

orphan process는 부모 프로세스가 자식보다 먼저 죽은 경우 발생한다.
zombie process는 자식 프로세스가 종료했음에도 부모가 뒤처리를 하지 않았을 때 발생한다.

📘 스레드

운영체제의 작업 단위는 프로세스라면, CPU의 작업 단위는 스레드이다.

프로세스 입장에서 정의하자면, 스레드는 프로세스의 코드에 정의된 절차에 따라 CPU에 작업 요청을 하는 실행 단위이다.

  • 멀티스레드 : 프로세스 내 작업을 여러 개의 스레드로 분할하여 작업의 부담을 줄이는 프로세스 운영 기법
  • 멀티태스킹 : 운영체제가 CPU에 작업을 줄 때 시간을 잘게 나누어 배분하는 기법
    • 시분할 시스템 time-sharing system : 여러 스레드에 시간을 잘게 나누어주는 시스템
  • 멀티프로세싱 : CPU를 여러 개 사용하여 여러 개의 스레드를 동시에 처리하는 작업 환경
  • CPU 멀티스레드 : 한 번에 하나씩 처리해야 하는 스레드를 파이프라인 기법을 이용하여 동시에 여러 스레드를 처리하도록 만든 병렬 처리 기법

✅멀티스레드

fork() 시스템 호출로 프로세스를 복사하면 코드 영역과 데이터 영역의 일부가 메모리에 중복되어 존재하고, 부모-자식 관계이지만 독립적인 프로세스이므로 낭비적인 요소가 많다.

따라서 이러한 멀티태스킹의 낭비 요소를 제거하기 위해 스레드를 사용한다.

멀티스레드는 하나의 프로세스 내에 여러 개의 스레드를 생성하고, 이 스레드가 코드, 파일 등의 정적인 자원은 서로 공유함으로써 자원의 낭비를 막고 효율성을 향상한다.

[멀티스레드 장점]

  • 응답성 향상 : 한 스레드가 입출력으로 인해 작업이 진행되지 않더라도 다른 스레드가 작업을 계속해 사용자의 작업 요구에 빠르게 응답할 수 있다.
  • 자원 공유 : 한 프로세스 내에서 독립적인 스레드를 생성하면 모든 스레드가 프로세스의 자원을 공유한다.
  • 효율성 향상 : 불필요한 자원의 중복을 막아 시스템의 효율이 향상된다.
  • 다중 CPU 지원 : 2개 이상의 CPU를 가진 컴퓨터에서 멀티스레드를 사용하면 다중 CPU가 멀티스레드를 동시에 처리해 CPU 사용량이 증가하고, 프로세스 처리시간이 단축된다.

[멀티스레드 단점]

  • 자원 공유 : 한 스레드에 문제가 생기면 전체 프로세스에 영향을 미친다.

멀티스레드 모델

커널 스레드사용자 스레드로 나뉜다.

  • 커널 스레드 kernel thread : 커널이 직접 생성하고 관리하는 스레드

    • 하나의 사용자 스레드가 하나의 커널 스레드와 연결되기 때문에 1 to 1 모델 이라고 부른다.
    • 독립적으로 스케줄링이 되기 때문에 특정 스레드가 대기 상태에 들어가도 다른 스레드는 작업을 계속할 수 있다.
    • 장점
      • 커널 레벨에서 모든 작업을 지원하기 때문에 멀티 CPU를 사용할 수 있다.
      • 하나의 스레드가 대기 상태에 있어도 다른 스레드는 작업을 계속할 수 있다.
      • 보안에 강하고 안정적으로 작동한다.
    • 단점
      • context switching을 할 때 오버헤드 때문에 느리게 작동한다.
  • 사용자 스레드 user thread : 라이브러리에 의해 구현된 일반적인 스레드

    • 커널 입장에서 일반 프로세스처럼 보이지만 커널이 하는 일을 라이브러리가 대신 처리하여 여러 개의 스레드를 작동한다.
    • 커널의 스레드 하나와 연결되기 때문에 1 to N 모델이라고 부른다.
    • 장점
      • 라이브러리가 직접 스케줄링을 하고 작업에 필요한 정보를 처리하기 때문에 context switching이 필요없어 속도가 빠르다.
    • 단점
      • 커널 스레드가 입출력 작업을 위해 대기 상태에 들어가면 모든 사용자 스레드가 같이 대기한다.
      • 한 프로세스의 타임 슬라이스를 여러 스레드가 공유하기 때문에 여러 CPU를 동시에 사용할 수 없다.
      • 커널 레벨에서는 공유 변수를 보호하는 장치가 있으나 사용자 스레드에서는 라이브러리에서 구현해야하기 때문에 보안에 취약하다.
  • 멀티레벨 스레드 multi-level thread : 사용자 스레드와 커널 스레드를 혼합한 방식

    • 커널 스레드의 개수가 사용자 스레드보다 같거나 적은 M to N 모델 이라고 부른다.
    • 장점
      • 하나의 커널 스레드가 대기 상태에 들어가면 다른 커널 스레드가 대신 작업을 해 사용자 스레드보다 유연하게 작업을 처리할 수 있다.
    • 단점
      • context switching을 할 때 오버헤드가 있어 사용자 스레드만큼 빠르지 않다.

📚 정리

프로세스는 운영체제의 작업 단위, 스레드는 CPU의 작업 단위이다.
프로세스는 생성, 준비, 실행, 대기, 완료 상태를 가질 수 있다.
멀티스레드를 통해 프로세스의 정적인 영역을 모든 스레드가 공유하게끔 하여 자원 관리의 효율성을 향상시킬 수 있다.

profile
🙇‍♀️ Android
post-custom-banner

2개의 댓글

comment-user-thumbnail
2022년 2월 3일

갓도연짱 역시 깐부님 대단해여

1개의 답글