250x250
기리도
기리도의 개발새발 개발 일지
기리도
전체 방문자
오늘
어제
  • 분류 전체보기 (44)
    • Unity (6)
      • 모듈식 프로그래밍 (1)
    • C# (10)
    • 자료구조,알고리즘 (2)
    • 운영체제 (10)
      • 공룡책 (3)
      • 그림으로 쉽게 배우는 운영체제(인프런 강의) (7)
    • 리팩토링 (1)
    • 네트워크 (13)
      • 네트워크 장비 (13)
    • C, C++ 문법 (1)
      • 기타 (0)
      • C (1)
      • C++ (0)
    • 디자인 패턴 (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • OS
  • 통신
  • 개발공부
  • 운영체제
  • 공부
  • Unity
  • 네트워크
  • 탄환
  • 브릿지
  • 프로그래밍
  • C#
  • 길찾기
  • 네트워킹
  • 유니티
  • 네트워크 게임
  • 스위치
  • 인프런
  • 개발
  • 게임개발
  • 알고리즘

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
기리도

기리도의 개발새발 개발 일지

운영체제/그림으로 쉽게 배우는 운영체제(인프런 강의)

프로세스와 쓰레드

2022. 3. 24. 15:43
728x90

https://inf.run/bXfg

 

그림으로 쉽게 배우는 운영체제 - 인프런 | 강의

이 강의를 통해 모든 개발자들이 필수로 알아야하는 운영체제의 원리를 알 수 있습니다., - 강의 소개 | 인프런...

www.inflearn.com

본 포스팅은 위 링크의 강의를 요약/정리한 것으로, 지식의 공유보다는 개인적으로 공부하고 복습하기 위해 기록한 것입니다.

 

프로그램과 프로세스

 

프로그램

🔗저장장치에 저장된 명령문의 집합체. 애플리케이션 혹은 앱이라 불린다(윈도우즈 운영체제의 .exe 파일)

프로세스

🔗저장장치에 저장된 프로그램이 메모리에 올라간 상태(간단히 말하면 실행 중인 프로그램)

🔗운영체제의 CPU 스케줄링 알고리즘에 따라 CPU를 사용하며 필요에 따라 입력과 출력을 한다 

🔗프로세스의 구조

  • 코드 영역: 프로그램을 실행하는 코드가 저장돼 있다
  • 데이터 영역: 전역 변수와 스태틱 변수가 저장돼 있다
  • 스택 영역: 지역 변수와 함수를 호출했을 때 필요한 정보가 저장된다(매개변수와 돌아갈 주소를 저장)
  • 힙 영역: 프로그래머가 동적으로 메모리를 할당하는 데에 쓰인다(런타임이 할당할 수 있는 메모리 공간). C언어에서는 malloc() 함수와 free() 함수를 호출해서 힙 영역에 자원을 할당하거나 할당을 해제할 수 있다.

🔗C언어는 컴파일 언어이기 때문에 반드시 컴파일 과정을 거쳐야만 코드를 실행할 수 있다

C언어에서 코드가 프로세스가 되는 과정

🔗(두 숫자를 더하는 코드를 실행한다고 했을 때)전처리기에서 매크로로 정의한 숫자를 치환하고 필요한 파일을 불러온다.

  • 전처리기: 프로그램의 조건에 맞추기 위한 사전 처리나 사전 준비적인 계산 또는 편성을 행하는 프로그램

🔗컴파일러가 고급 언어인 C언어를 저급 언어인 어셈블리어로 바꿔준다.

🔗어셈블러가 어셈블리어를 기계어로 바꿔준다.

🔗마지막으로 링커가 여러 라이브러리나 다른 소스코드들을 연결한다.(링킹)

🔗이 과정을 거치면 파일의 확장자는 .exe가 되며, .exe 파일이 실행되어 메모리에 올라가면 프로세스가 된다.

  • 링커: 두 개 이상의 목적 프로그램을 합쳐서 실행 가능한 한 개의 프로그램으로 만드는 작업을 하는 프로그램

프로세스가 실행되는 과정

🔗CPU 내 제어장치가 계산할 숫자를 메모리에 저장한다.

🔗그 후 메모리에 저장된 값을 edx, eax 레지스터로 가져온다.

🔗제어장치가 레지스터에 저장된 숫자를 계산하라고 명령한다.

🔗산술논리 연산장치가 저장된 숫자를 계산하고 그 결과를 eax 레지스터에 저장한다.

🔗마지막으로 제어장치가 eax 레지스터에 저장된 결과값을 메모리에 저장한다.


멀티프로그래밍과 멀티프로세싱

 

멀티프로그래밍

🔗메모리 관점에서의 정의

🔗메모리에 여러 개의 프로세스가 올라온 것

  • 반대로 오직 하나의 프로세스만 메모리에 올리는 것을 유니프로그래밍이라고 한다. 과거에는 메모리의 크기가 작아서 유니프로그래밍을 하면서 멀티프로세싱을 이용했다.
  • 유니프로그래밍 환경에서의 멀티프로세싱
    1. 메모리에 프로세스를 올려서 CPU로 처리한 후 다른 저장장치에 저장한다.
    2. 다른 저장장치에 있던 프로세스를 메모리에 올려서 CPU로 처리한다.

 

멀티프로세싱

🔗CPU 관점에서의 정의

🔗CPU가 여러 개의 프로세스를 처리하는 것

🔗CPU가 시분할 처리로 각각의 프로세스를 짧은 시간 동안 교대로 실행


PCB

PCB

🔗Process Control Block의 약자

🔗프로세스가 만들어지면 운영체제는 해당 프로세스의 정보를 가진 PCB를 연결리스트로 생성해 저장한다.

🔗운영체제는 프로세스가 종료되면 연결리스트에서 해당 프로세스의 PCB를 제거한다.

🔗PCB의 구조

  • 포인터
    • 부모와 자식 프로세스에 대한 포인터, 할당된 자원에 대한 포인터, 프로세스의 상태를 저장하는 포인터 등
    • 효율적인 접은을 위해 사용한다
  • 프로세스 상태
    • 현재 프로세스의 다섯 가지 상태(생성, 준비, 실행, 대기, 완료)를 나타낸다.
  • 프로세스 ID
    • 프로세스를 식별하기 위한 숫자를 저장
  • 프로그램 카운터
    • 다음에 실행될 명령어의 주소를 포함
    • 시분할 처리 과정에서 프로세스가 실행을 멈췄다가 다시 실행될 때 이어서 작업할 수 있게 한다.
  • 레지스터 정보
    • 프로세스가 실행될 때 사용한 레지스터 값을 저장한다. 프로그램 카운터와 마찬가지로 이전 작업을 이어서 할 수 있게 한다.
  • 메모리 관련 정보
    • 프로세스의 메모리상 위치 정보, 메모리 침범을 막기 위한 경계 레지스터 값 등을 저장
  • CPU 스케줄링 정보
    • CPU 스케줄링에 필요한 우선 순위, 최종 실행 시간, CPU 점유 시간 등을 저장

프로세스 상태

 

프로세스의 상태

🔗프로세스에는 시분할 처리를 위한 다섯 가지 상태가 있다

🔗생성

  • PCB를 생성하고 메모리에 프로그램 적재를 요청한 상태
  • 적재를 승인받은 후 준비 상태로 이동

🔗준비

  • CPU를 사용하기 위해 기다리는 상태
  • 준비 상태의 프로세스는 CPU 스케줄러에 의해 CPU를 할당받음

🔗실행

  • 준비 상태에서 CPU 스케줄러에 의해 선택된 프로세스가 실행되고 있는 상태
  • 실행 상태에 있는 프로세스의 숫자는 CPU의 숫자와 같다
  • 실행 상태에 있더라도 부여된 시간만큼만 CPU를 사용할 수 있다
  • 부여된 시간을 모두 사용하면 다시 준비 상태로 돌아간다

🔗대기

  • 프로세스가 입출력 요청을 하면 입출력이 완료될 때까지 기다리는 상태
  • CPU의 속도에 비해 입출력 작업은 느리다. 이를 해결하기 위해 입출력 요청을 한 프로세스를 대기 상태에 두고 다른 프로세스를 먼저 실행한다. 그 후 입출력 작업이 완료되면 대기 상태에 있던 프로세스를 준비 상태로 옮겨서 실행되도록 한다.

🔗완료

  • 프로세스가 종료된 상태
  • 프로세스가 사용한 데이터를 메모리에서 제거하고 생성된 PCB도 제거한다.

컨텍스트 스위칭

 

컨텍스트 스위칭

🔗프로세스를 실행하는 중에 다른 프로세스를 실행하기 위해 실행 중인 프로세스의 상태를 저장하고 다른 프로세스의 상태값으로 교체하는 작업

🔗컨텍스트 스위칭이 일어나면 PCB의 내용이 변경된다

  • 실행 중인 프로세스의 작업 내용을 PCB에 저장하고 실행될 프로세스의 PCB 내용대로 CPU가 세팅된다
  • 프로세스 상태, 프로그램 카운터, 각종 레지스터 값 등이 변경된다

프로세스 생성과 종료

 

프로세스 생성 과정

🔗프로그램의 코드 영역과 데이터 영역을 메모리에 로드하고 빈 스택과 힙을 만들어 공간을 확보한다.

🔗프로세스를 관리하기 위한 PCB를 만들어서 값을 초기화한다.

🔗프로세스 생성 과정은 운영체제가 부팅되고 0번 프로세스가 생성될 때 딱 한 번만 실행된다.

  • 나머지 모든 프로세스는 fork() 함수를 이용해 0번 프로세스를 복사해서 쓴다. 복사해서 쓰는 게 더 빠르기 때문.
  • 복사해서 생성된 프로세스를 자식 프로세스라고 하며, 0번 프로세스는 부모 프로세스가 된다.
  • 이후 exec() 함수를 실행하면 자식 프로세스의 코드와 데이터 영역을 원하는 값으로 덮어쓰게 된다.

🔗예제 코드

부모 프로세스

#include <stdio.h>
#include <unistd.h>

int main()
{
  int pid;
  pid = fork();  //부모 프로세스에게는 0이 아닌 숫자를 반환
  
  if(pid == 0)  //자식 프로세스
  {
    execlp("InternetBrowser", "0", NULL);
    exit(0);
  }
  else // 부모 프로세스
  {
    wait(NULL);  //자식 프로세스에서 exit() 신호가 올 때까지 기다렸다가 신호가 오면 종료시킴
    printf("인터넷 브라우져 닫힘");
    exit(0);
  }
}

자식 프로세스

#include <stdio.h>
#include <unistd.h>

int main()
{
  int pid;
  pid = fork();  //자식 프로세스에는 0을 반환
  
  if(pid == 0)  //자식 프로세스
  {
    execlp("InternetBrowser", "0", NULL);  //인터넷 브라우저 프로그램 실행 후 해당 프로그램에서 코드와 데이터 영역을 가져와 덮어씀
    exit(0);  //프로세스 종료를 알림
  }
  else // 부모 프로세스
  {
    wait(NULL);  //
    printf("인터넷 브라우져 닫힘");
    exit(0);
  }
}

🔗두 프로세스 중 어떤 프로세스가 먼저 실행될지는 운영체제가 선택한다.

🔗부모 프로세스가 자식 프로세스보다 먼저 종료되거나 자식 프로세스가 비정상적으로 종료돼 exit() 신호를 주지 못해서 메모리에 계속 살아 있는 상태를 "좀비 프로세스"라고 부른다.


쓰레드

 

쓰레드

🔗프로세스가 메모리를 많이 차지하는 문제를 해결하기 위해 고안된 작업의 실행 단위

🔗한 프로세스 내의 쓰레드들은 그 프로세스의 PCB, 코드, 데이터, 힙 영역을 공유한다. 스택은 쓰레드마다 각각 가지고 있다.

🔗쓰레드 ID: 쓰레드를 구분하기 위한 식별자

🔗Thread Control Block(TCB): 쓰레드를 관리함

🔗프로세스를 복사해서 새로 생성하는 대신 쓰레드를 여러 개 추가해서 메모리를 절약한다.

 

프로세스 vs 쓰레드

🔗프로세스

    • 프로세스는 서로 독립적이기 때문에 한 프로세스에 문제가 생기더라도 다른 프로세스가 영향을 받지 않는다.(안정성 좋음)
    • 오버헤드가 크고 속도가 느리다.(각 프로세스마다 PCB와 데이터, 힙, 스택 영역을 전부 갖고 있고 프로세스간 통신에 IPC를 이용하기 때문)

🔗쓰레드

    • 쓰레드는 하나의 프로세스 내에 존재하기 때문에 해당 프로세스에 문제가 생기면 그 안의 모든 쓰레드에 문제가 생긴다.(안정성 나쁨)
    • 한 프로세스 내에서 스택 영역을 제외한 모든 영역을 공유하기 때문에 오버헤드가 적다.
728x90
저작자표시 (새창열림)

'운영체제 > 그림으로 쉽게 배우는 운영체제(인프런 강의)' 카테고리의 다른 글

메모리 종류  (0) 2022.03.29
데드락  (0) 2022.03.29
프로세스 동기화  (0) 2022.03.28
CPU 스케줄링  (0) 2022.03.25
운영체제 들어가기  (0) 2022.03.21
    '운영체제/그림으로 쉽게 배우는 운영체제(인프런 강의)' 카테고리의 다른 글
    • 데드락
    • 프로세스 동기화
    • CPU 스케줄링
    • 운영체제 들어가기
    기리도
    기리도
    공부한 내용을 정리해서 올리는 블로그입니다.

    티스토리툴바