컴퓨터과학/0 +운영체제

[운영체제] 4. Processes and Threads(프로세스와 스레드)

힘들면힘을내는쿼카 2022. 3. 26. 15:17
728x90
반응형

2022.03.21 - [컴퓨터 공학/0 +운영체제] - [운영체제] 2. Interrupts

 

[운영체제] 2. Interrupts

2022.03.06 - [컴퓨터 공학/0 +운영체제] - [운영체제] 1. 컴퓨터 구조(CPU 동작원리) [운영체제] 1. 컴퓨터 구조(CPU 동작원리) 특수대학원을 다니면서 운영체제 강의 내용을 정리하려고 한다. 이번 글은

howisitgo1ng.tistory.com

 

 

프로세스와 스레드...

우리는 이 단어에 대해서 정말로 정말로 정말로 많이 들었지만, 정확한 개념을 이해하지 못한채로 사용했을 것이다.

오늘 둘의 개념에 대해서 파헤쳐보자! 😼

 

이 질문에 답하기 전에 컴퓨터 프로그램이란 무엇인지 생각해보자!

컴퓨터 프로그램이란 실행될 때 특정 작업(specific task)을 수행하는 일련의명령어들의 모음(파일)이다.

즉, 간단히 말하면 작업을 위해서 실행 할 수 있는 파일이다.

 

그렇다면 프로세스란...?

컴퓨터에서 연속적으로 실행되고 있는 컴퓨터 프로그램을 뜻한다.

추가로 설명하자면,

메모리에 올라와서 실행되고 있는 프로그램의 인스턴스

운영체제로부터 시스템 자원을 할당받는 작업의 단위

실행된 프로그램을 의미!!!

 

스레드란?

프로세스 내에서 실행되는 여러 흐름의 단위

 

위 3가지 개념을 도식화 하면 다음과 같다.

 프로그램을 실행하면 프로세스...!!!

 

다시 한번 설명하자면
신문이 있다. 신문은 정적인 상태이므로 프로그램이다.
당신이 신문을 읽는다. 신문을 읽는 것은 동적인 상태 이므로 프로세스이다.
신문 안에는 여러가지 컬럼들이 있다. 스포츠, 만화, 연예 등등... 이러한 컬럼들을 읽는 당신이 스레드 이다.

정리
신문 = 프로그램
신문을 읽는 당신 = 프로세스
신문 안에 여러 컬럼을 읽는 당신 = 스레드

😎

 

 


 

이제 프로세스와 스레드의 세부적인 특징들에 대해서 알아보자..

 

프로세스

CPU는 한 순간에 오직 한 개의 프로세스를 실행하며 빠르게 다른 프로세스를 전환하여 병렬 작업 ---> 의사 병렬성

사용자의 입장에서는 동시에 여러 작업을 수행하는 것처럼 보이지만, 실제로는 하나의 작업을 돌아가면서 실행하는 것이다.

프로세스 A, B, C

 

프로세스 A, B, C가 순서대로 실행되고 있는 예를 보자.

5000에서 프로세스를 실행하고 있다.

5005번지에서 인터럽트가 발생하면 프로세스는 해당 작업을 멈추고, 인터럽트에 해당하는 작업(100 ~ 105)을 수행한다.

인터럽트를 실행하는 주체는 process이다.

운영체제는 프로세스의 형태가 아니다.

운영체제의 code를 실행하는 주체는 process!!!!!!!

5000~105까지 실행하는 주체는 process A

이후 interrupt return 으로 다음 process B의 시작번지를 넘긴다.

process B는 8000~8003를 실행하고 인터럽트 신호를 받으면 100 ~ 105까지 실행한 뒤, process C의 시작주소를 return 한다.

이런 방식으로 프로그램을 실행한다.


프로세스가 할당받는 자원은 다음과 같다.

  • cpu 시간
  • 운영되기 위해 필요한 주소공간
  • code, data, stack, heap의 구조로 된 메모리 영역

프로세스는 code, data, stack, heap의 구조로 되어 있는 독립된 메모리 영역을 할당 받는다. (이들을 각각 segment로 부른다.)

참고: https://box0830.tistory.com/150

 

메모리 영역(Code, Data, Heap, Stack)

이게 매번 헷갈려서 확실히 정리를 할 필요가 있겠네요. 프로세스가 차지하고 있는 메모리를 살펴보면 크게 Code, Data, Heap, Stack의 영역으로 나누어져 있습니다. 이들 각각을 segment라 불러요. - 메

box0830.tistory.com

 

각 프로세는 별도의 주소 공간에서 실행되고, 서로 독자적인 메모리 공간을 갖기 때문에 메모리를 공유할 수 없다. 즉, 다른 프로세스의 변수나 자료구조에 접근이 불가하다...!

e.g) process A와 process B는 서로 변수를 공유 할 수 없다.  why? --> 서로 독자적인 메모리에서 동작하기 때문.

다른 프로세서의 자원에 접근하기 위해서는...? ---> 프로세스간의 통신(ipc)를 사용해야 한다.

프로세스는 최소 하나 이상의 스레드를 포함.


프로세는 실행되면서 여러 상태가 존재 한다.

우선, 프로세서가 언제 생성되고 종료되는지 알아보자...!!

프로세스 생성 과정

  • 시스템 초기화 과정(최초의 부모 프로세스)
  • 실행중인 프로세스에 의한 프로세스 생성 시스템 호출 실행(부모 프로세스가 자식 프로세스 생성)
  • 사용자가 새로운 프로세스 생성을 요청할 때
  • 일련의 작업을 초기화 할 때

 

프로세스 종료 과정

  • normal exit(자발적)
  • error exit(자발적)
  • fatal error(비자발적)
    • 에러가 발생하면(인터럽트 발생, user mode -> kernel mode) 운영체제가 강제로 종료
  • killed by another process(비자발적)
    • signal을 받아서 종료되는 경우(kill -9) ------> 자식 프로세스를 강제로 종료
      • 자식 프로세스가 할당된 자원을 초과하여 사용할때
      • 자식 프로세스에게 주어진 작업이 필요하지 않을 때
      • 부모 프로세스가 종료된 후 자식 프로세스의 실행이 허용되지 않는 시스템인 경우

프로세스의 상태

상태를 알기 전에 dispatcher를 알아야한다.

dispatcher는 os프로그램의 일부로, 실행중인 프로세스을 중단하고 다른 프로세스을 실행시키도록 하는 프로그램이다. (CPU에 할당)

intterupt(timeout, I/O request)가 발생하거나 종료된 프로세스로부터 준비 중인 프로세스를 수행 상태로 만들 때 항상 dispatcher가 실행 된다.

Ready Queue: 현재 메모리 내에 있으면서 cpu에 잡아서 실행되기를 기다리는 프로세스의 집합.

Event n Queue: 인터럽트가 발생한 프로세스를 저장하는 큐, 여기서 대기, Blocked 상태

 

반응형

 

  •  new
    • 프로세스가 만들어진 상태
      • 프로세스가 생성되면 바로 ready 단계로 가면 안될까? 프로세스가 만들어지면 메모리도 할당해야하고 프로세스의 정보를 담고 있는 pcb와 프로세스가 실행되면서 사용할 스택 메모리도 할당하고 초기화도 해줘야한다. 그래서 프로세스 생성에는 시간이 걸리고 어느정도 new상태에 머물러야함.
  • ready
    • 실행을 하기위해 기다리는 상태
      • 언제든지 실행할 준비가 되어있다. cpu를 할당해주면 바로 실행 할 수 있는 단계
  • running
    • 프로세스가 cpu를 차지하고 실행하고 있는 상태
  • blocked
    • cpu를 할당해주어도 실행할 수 없는 상태.
      • Interrupt 또는 다른 프로세스가 끝날 때가지 대기 등등 같은 상황
  • exit
    • 프로세스가 끝나게 되면 프로세스가 할당 받았던 자원들을 반납하는 상태
      • exit상태에서도 new와 마찬가지로 실제 종료되는 데 까지 시간이 걸리는데 이러한 상태를 좀비 상태라고 부른다.
  • suspend
    • 메모리에 꺼내서 하드디스크로 옮기는 단계
      • Queue에 있는 프로그램의 포인터를 이용하여 옮긴다.

 

  • New --(admit)--> Ready
    • new상태에서 Ready 상태에서 자연스럽 넘어가는 것이 아니라 os가 ready단계로 가도록 허락(admit)할 때 넘어 갈 수 있다.
      1. 메모리 공간은 한정적이고, 메모리에 올릴 수 있는 프로그램도 한정적이기 때문이다.
      2. cpu는 프로그램을 time sharing을 통해 동시에 진행하는 것 처럼 보이게 한다. 하지만 프로그램이 많아지면 각 프로그램으리 대기 시간이 길어지게 되고 이는 버벅이는 것처럼 보여 문제가 될 수 있음. 
  • Ready --(dispatch)--> Running
    • Dispatcher가 대기하고 있는 프로그램 중 적절한 프로그램을 골라 running상태로 옮긴다.
    • ready상태에서 running상태로 보낼 프로세스를 고르는 과정을 scheduling이라고 한다.
  • Running --(release)--> Exit
    • os는 프로그램이 종료하게 되면 exit상태로 옮긴다.
  • Running --(timeout)--> Ready
    • cpu는 time sharing을 통해 프로세스들을 실행시키므로 프로그램이 길면 timeout이 걸려 ready상태로 돌아가게 된다.
  • Running --(event wait)--> Blocked
    • 프로그램 실행 중 event(i/o request, os에 작업 요청)가 발생하면 blocked상태로 변경된다.
  • Blocked --(event occurs)--> Ready
    • 기다리던 이벤트가 발생되어 종료되면 running상태로 바로 가지 않고 ready상태로 된다.
  • Blocked --(suspend)--> Blocked/Suspend(의도적으로 중단)
    • 메모리에 올라와 있는 프로세스들이 모두 요청한 작업을 하느라 blocked상태이고, 하드디스크에 swapped 되었던 프로세스들을 메모리에 올려야한다. 따라서 메모리에 있던 프로세스들을 하드디스크의 swapped area로 옮긴다.
      • swapping? 
        • 메모리의 크기는 한정적이기 때문에 메모리에 올릴 수 있는 프로그램의 수는 한정적이다.
        • 메모리에 올라온 프로세서들이 모두 blocked이 되면 cpu가 하는 일이 없어진다. 그렇기 때문에 하드디스크에서 대기 중인 프로세서들을 메모리에 올리고 기존 메모리에 있던 프로세서들(blocked 상태 프로세서)은 하드디스크로 내린다.
  • Blocked/Suspend --(active)--> Blocked
    • 요청한 작업이 다 끝나지 않았지만 메모리에 공간이 충분히 있을 경우 다시 메모리로 올라갈 수 있다.
  • Blocked/Suspend --(event occurs)--> Ready/Suspend
    • 요청한 작업이 다 끝났지만 메모리에 공간이 없는 경우 ready/suspend상태로 변경한다.
  • Ready/Suspend --(active)--> Ready
    • 대기하던 중 메모리에 공간이 생겨 다시 ready상태로 변경.
  • Ready --(suspend)--> Ready/Suspend(의도적으로 중단)
    • 메모리에 공간을 만들어야 할 경우 ready/suspend상태로 변경.
  • New --(admit)--> Ready/Suspend
    • 메모리가 다 찬 경우 os는 new상태에서 ready/suspend 상태로 admit한다.

 


 

프로세스의 실행

프로세스 구조 운영체제의 가장 낮은 레이어는 인터럽트와 스케줄링을 처리한다.

아래 그림은 그 레이어 위의 순차적인 과정을 표현한 것이다.

다음은 프로세스의 테이블에 대한 표 이다.

process, memory, file로 나누어 짐을 알수 있다.

 

다음은 프로세스의 실행 과정이다.

1. 하드웨어 프로그램 카운터 등을 스택한다.
2. 하드웨어가 인터럽트 벡터로부터 새로운 프로그램 카운터를 로드합니다.(user mode --> kernel mode)
3. 어셈블리 언어 절차로 레지스터를 저장합니다.
4. 어셈블리 언어 절차에서 새 스택을 설정합니다.(user stack --> kernel stack)
5. C 인터럽트 서비스가 실행됩니다(일반적으로 읽기 및 버퍼 입력).
6. 스케줄러는 다음에 실행할 프로세스를 결정합니다.
7. C 절차는 어셈블리 코드로 돌아갑니다.
8. 어셈블리 언어 절차는 새로운 현재 프로세스를 시작합니다.

일반적으로 1 -> 2 -> 3 -> 4 -> 3 -> 2 -> 1 과정을 반복함.

 


 

728x90

 

스레드

  • 프로세스가 할당 받은 자원을 이용하는 실행 단위이자, 프로세스의 특정한 수행경로이자, 프로세스 내에서 실행되는 여러 흐름의 단위
  • 스레드는 프로세스내에서 프로세스의 자원을 이용해서 실제로 작업을 수행하는 일꾼.
  • 스레드가 소속된 프로세스가 운영체제로부터 자원을 할당받으면 그 자원을 스레드가 사용.
  • 프로세서는 최소 한 개 이상의 스레드를 가지며 이 스레드를 메인 스레드(main thread)라고 함.

하나의 porcess안에서 병행으로 작업을 처리하고 싶어서 등장함....!

A multithreaded web server

 

코드로 설명하면 다음과 같다.

(a) = Dispathcer thread

(b) = Worker thread


스레드 모델은 다음과 같다.

finite-sate machine의 nonblocking system calls은 운영체제의 ready queue에 들어가지 않고, 실행여부와 관계없이 바로 응답을 보내는 경우 이다.

우리는 일반적으로 Threads모델을 사용한다.


 

스레드의 특징은 다음과 같다.

  • 각 스레드는 독자적인 스택(stack)메모리를 갖는다.
  • 스레드는 프로세스 내에서 각각 stack만 할당 받고 code, data, heap 영역은 공유함.
  • 스레드는 한 프로세스 내에서 동작되는 여러 실행의 흐름이기 때문에 프로세스 내의 주소공간이나 자원들을 같은 프로세스 내의 스레드끼리 공유하며 실행된다.
  • 각각의 스레드는 별도의 레지스터와 스택을 갖고 있지만, 힙 메모리는 서로 읽고 쓸수 있다.
  • 한 스레드 프로세스 자원을 변경하면, 다른 이웃 스레드도 변경 결과를 즉시 볼 수 있다.
  • 스레드는 메모리를 공유하기 때문에 동기화, 데드락 등의 문제가 발생 할 수 있다.
  • 스레드는 대대분의 현대 운영체제가 지원하고 있다.

 

 

각각의 스레드는 각각의 스택을 갖고 있다.(스택에는 함수의 내부변수들을 저장함)

each thread has its own stack

 


Posix Threads(Unix의 스레드 패키지)

some of the Pthreads function calls

 

example code of posix threads

 


user-level threads package

옛날 운영체제는 멀티 스레드가 아니였다. 프로세스 개념만 있었다.

그런데 사람들이 멀티 스레드를 원하자, 운영체제 개발사는 멀티 스레드를 지원하는데 시간과 연구(돈)가 필요했기 때문에

user-level threads package를 고안하게 된다.

user-level threads package는 미니 운영체제 역할을 한다.

시스템 입장에서는 프로세스 하나만 실행하는 것으로 보임.

좌: a user lever threads package, 우: threads parkage managed by the kernel

지금은 우측 그림처럼 kernel level에서 스레드를 관리한다.(스레드 단위로 스케줄링)

 


kernel-level 스레드를 만드는 비용보다 user-level 스레드를 만드는 비용이 훨씬 저렴해서 나온 방법

성능과 가격을 동시에 잡기 위함.


Pop-up threads

팝업 기능만 전담으로 담당하는 스레드.


​운영체제가 최초에 단일 프로세스만 생각하고 개발 되었다보니, 멀티 스레드 개념이 들어오고 나서 많은 문제점들이 발생하게 됨.

특히, 프로그래밍 언어에서 많이 발생함.

conflicts between threads over the use of global variable

 

thread1 에서 errno를 set 하고 error 여부를 체크 해야하는데,

thread2가 실행됨, thread2도 시스템을 호출하여 error여부를 체크함.

이때 검출된 errno는 thread2의 것. -----> thread1것은 사라짐... 🙀

 

그래서 전역 변수들을 thread 마다 가져야 한다...!라는 것은 인지하고 아래와 같이 변경함.

 

 

 

728x90
반응형