[CS 스터디-OS] 프로세스/쓰레드/동기화

똘맹·2023년 3월 18일

CS 스터디

목록 보기
2/20
post-thumbnail

이 글은 반효경 교수님의 운영체제 강의 및 교재를 참고합니다.

📢 들어가며

프로그램이 요구하는 태스크를 운영체제가 어떻게 수행하고 관리하는가?




1. 프로세스란?

프로그램, 프로세스를 구분해보자.

  • 프로그램: 우리가 눈으로 볼 수 있도록 파일로서 저장된 것. 실행 파일.
  • 프로세스: 실행 파일을 실행하여 메모리에 올라간 것. 프로그램의 하나의 객체, 인스턴스라고 표현할 수 있음.

CPU가 하나인 싱글 코어 컴퓨터를 가정해보자. 쓰레드의 개념을 적용시키지 않는다면, 특정 시간에 처리할 수 있는 작업은 오직 하나 뿐이다. CPU는 정말 빠르고 성능이 좋지만, 만약 어떤 프로그램이 엄청나게 많은 시간을 잡아먹는 작업을 시작했다고 하자. 그럼 그 시간 동안 다른 작업을 미루어 둔 채 해당 작업에 전념해야만 할까?

물론 그렇지 않을 것이다. 이러한 시간의 간극을 채우기 위해 도입된 개념이 "Process Context"이다. 프로세스의 문맥을 어딘가에 저장해두고, 다른 프로세스로 넘어가면 앞서 말한 간극을 해결할 수 있다. 어차피 CPU가 Device에 직접 접근하는 것이 아니기 때문에 가능한 이야기이다.

(1) 프로세스 메모리 구조

특정 시점에서 프로세스가 어디까지 수행을 했는지 나타내기 위해 필요한 요소들을 프로세스의 문맥이라고 지칭한다. 프로세스의 문맥을 저장하기 위해, 프로세스 메모리 구조는 다음의 항목을 포함한다.

source: https://velog.io/@cchloe2311/%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B5%AC%EC%A1%B0

  • stack: 잠시 사용되었다가 사라지는 데이터가 저장됨. 함수 호출 시 할당되고 함수 반환 시 소멸되며, 로드 시 크기가 결정됨.

  • code: 실행할 프로그램의 코드가 저장됨. CPU는 여기에서 명령어를 하나씩 가져와서 처리함.

  • data: 전역 변수 및 정적 변수가 저장됨. 프로그램이 시작될 때 할당되고 프로그램 종료 시 소멸됨.

    stack, code, data는 컴파일 시 메모리 영역이 결정됨.

  • heap: 포인터 변수 등이 저장되는 동적 데이터 영역. 메모리 주소 값에 의해서만 참조되고 사용됨. 프로그램 동작 시 크기가 결정됨.

++
Process Context

  • CPU 수행 상태를 나타내는 하드웨어 문맥
    CPU의 PC가 해당 프로세스의 code 영역 중 어디를 가리키고 있었고/어떤 내용을 얼마나 stack에 쌓아두고 있었는지 등의 정보
  • 프로세스 주소 공간
    stack, data, code의 주소 공간 자체
  • 프로세스 관련 커널 자료 구조
    프로세스가 하나 생길 때마다 운영체제가 커널에 해당 프로세스와 관련하여 생성한 정보(PCB 등). 해당 자료 구조를 통해 커널이 프로세스를 관리함.

(2) 프로세스 상태 변화와 PCB

프로세스가 System Call을 했을 때 Program Counter는 그 프로세스의 code를 가리키는 것이 아니라, 커널의 code를 가리키면서 커널 스택에 저장한다. 이때 프로세스마다 커널 스택을 달리하게 된다.

  • PCB: 운영체제가 각 프로세스를 관리하기 위해 프로세스당 유지하는 정보. 구조체로 유지되어 있으며 다음의 구성 요소를 가짐.
    • OS가 관리상 사용하는 정보
      • Process state, Process ID
      • scheduling information, priority
    • CPU 수행 관련 하드웨어 값
      • Program Counter, registers
    • 메모리 관련
      • code, data, stack의 위치 정보
    • 파일 관련
      • Open file descriptors 등

이러한 프로세스 문맥을 통해 프로세스들이 번갈아가며 CPU를 점유하기 때문에, 프로세스 상태라는 개념이 등장하게 된다. 기본적으로는 다음과 같은 상태가 있다.

  • Running: CPU를 잡고 instruction을 수행 중인 상태
  • Ready: CPU를 기다리는 상태. 메모리 등 다른 조건(준비)은 모두 만족(완료)한 상태
  • Blocked(wait, sleep): CPU를 주어도 당장 instruction을 수행할 수 없는 상태. 프로세스 자신이 요청한 event(ex: I/O)가 즉시 만족되지 않아 이를 기다리는 상태. ex) 디스크에서 file을 읽어와야 하는 경우
  • New: 프로세스가 생성 중인 상태
  • Terminated: 수행(execution)이 끝난 상태

운영체제는 프로세스의 상태를 기반으로 프로세스를 관리하며, 이 때 queue를 사용한다. 다음의 그림을 참고하면 이해가 쉽다.

(3) Context-Switching

  • Context-Switching: CPU를 한 프로세스에서 다른 프로세스로 넘겨주는 과정
    -> CPU가 다른 프로세스에게 넘어갈 때 운영체제는 다음을 수행한다.
    • CPU를 내어주는 프로세스의 상태를 그 프로세스의 PCB에 저장
    • CPU를 새롭게 얻는 프로세스의 상태를 PCB에서 읽어옴

문맥 교환은 interrupt 혹은 system call에 의해 발생한다. 이에는 두 가지 양상이 존재한다.

  1. 문맥 교환이 발생하지 않는 경우


  2. 문맥 교환이 발생하는 경우(1보다 overhead가 훨씬 크다)

(4) 프로세스간 의사소통 - IPC



2. 쓰레드란?


(1) 쓰레드의 구조와 공유 영역

(2) 싱글 쓰레드와 멀티 쓰레드

(3) 프로세스 내에 여러 개의 쓰레드를 사용하는 이유



3. 프로세스와 쓰레드의 차이



4. 프로세스 동기화 기법


(1) 임계 영역

(2) Mutex, Semapore


참고

profile
척척학사가 되고 싶은 똘맹

0개의 댓글