CPU는 결국 시스템내에 하나밖에 존재하지 않으므로, 일반적으로 여러프로그램이 동시에 수행되는 시분할

환경에서 CPU는 매우 효율적으로 관리되어야 한다.

 

그렇다면 시분할 시스템에서 타이머인터럽트에 의해, 혹은 I/O요청에의해 다른프로세스로의 CPU할당이 일어날때 굳이 스케줄링 기법이 필요한 이유가 무엇일까.

이에대해 잠시 CPU버스트와 I/O버스트를 알고 넘어가자.

 

 

CPU버스트란, 프로그램이 CPU를 직접 가지고 빠른 명령(add,Load등의 기계어)을 수행하며, 프로그램이 I/O를 한번 수행후 다음번 I/O를 수행하기까지 직접 CPU를 가지고 명령을 수행하는 일련의 작업이다.

 

I/O버스트란,  I/O 요청이 발생해 커널에의해 입출력 작업을 진행하는 비교적 느린 작업이다.

 

각프로그램은 두개의 작업을 모두 포함하나, 두개의 차지하는 비율이 균일하지는 않다.

CPU버스트가 빈번한 프로세스를 CPU 바운드 프로세스라고 하며, I/O버스트가 빈번한 프로세스를 I/O바운드 프로세스라고 한다. 이렇듯 CPU를 사용하는 패턴이 상이한 여러 프로그램이 동일한 시스템 내부에서 함께 실행되기 때문에 CPU스케줄링 기법이 필요하다.

 

예를들어 대부분의 프로세스들은 CPU연산보다 I/O작업을 처리하는 비중이 큰데, 이 경우 사용자에게 입력이 들어왔을때 CPU의 빠른처리를 필요로 한다. 대화형 작업이므로, CPU의 빠른 응답또한 중요하다는 것이다. 따라서 이경우는 CPU버스트가 짧은 프로세스에게 우선적으로 CPU를 사용할 수 있도록하는 스케줄링이 필요한 것이다. 이는 결국 빠른응답으로 인한 I/O장치의 이용률을 높여 효율을 높이는 결과를 가져온다. 

 

 

 

<CPU 스케줄링이 발생하는 경우>

 

1)실행상태의 프로세스가 I/O요청에 의해 봉쇄상태로 바뀌는 경우

2)실행상태의 프로세스가 타이머 인터럽트 발생에 의해 준비상태로 바뀌는 경우

3)I/O 요청으로 봉쇄상태에 있던 프로세스의 I/O작업이 완료되어 인터럽트가 발생하고 그 결과 이 프로세스의 상태가 준비상태로 바뀌는 경우

4)CPU에서 실행상태에 있는 프로세스가 종료되는 경우

 

<선점형(preemptive) 스케줄링과 비선점형(nonpreemptive) 스케줄링>

 

선점형 스케줄링 : 프로세스가 CPU를 계속 사용하기를 원하더라도 강제로 빼앗을수있는 방식

비선점형 스케줄링 : CPU를 휙득한 프로세스가 스스로 CPU를 반납하기 전까지는 CPU를 계속 사용하는 방식

 

 

 

 

스케쥴링 알고리즘

 

https://velog.io/@pa324/%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C-%EC%8A%A4%EC%BC%80%EC%A5%B4%EB%A7%81-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EA%B8%B0%EB%B3%B8-uwk12tlqwj

 

운영체제 - 스케쥴링 알고리즘 기본

프로세스란 ? 실행중인 프로그램은 프로세스라고 한다. 메모리에 올려져서, 실행 중인 프로그램 모든 코드는 메모리에 올려진 후 한줄 씩 cpu에서 실행되는 구조이다. 코드이미지(바이너리) : 실�

velog.io

 

 

 

 

 

 

 

 

 

     <IPC 기법>

  1. file 사용
  2. message queue
  3. shared memory
  4. pipe
  5. signal
  6. semaphore
  7. socket

 

 

IPC의 종류와 특징

IPC(Inter Process Communication) - 프로세스 간 통신에 대하여 종류와 특징들에 대하여 살펴보겠습니다. [리눅스 커널 구조] - 위 그림처럼 Process는 완전히 독립된 실행객체입니다. 서로 독립되어 있다��

jwprogramming.tistory.com

 

 

1.프로세스의 생성

 

프로세스를 생성하는 방법은 exec 계열의 함수를 이용해 생성하는 것이다. 현재 프로세스에서 어떠한 것을 실행한다라는 의미로 해석된다. 하지만 이렇게 프로세스를 생성하면 현재 프로세스의 상태를 완전히 덮어버리게 된다. 이것은 운영체제는 동시에 단지 하나의 프로세스만을 가질수 있다는 것이다.

따라서 리눅스에서 프로세스는 사용자가 생성할수 있으나, 프로세스가 또다른 프로세스를 생성하는것도 가능하다.

이를 통해 진정한 멀티프로세스 환경을 제공한다.

 

Tree of Processes in Linux

 

fork를 통해 부모프로세스로부터 생성된 자식프로세스는 부모로부터 많은 정보들을 그대로 상속받는다.  

위의 그림처럼 계속해서 자식프로세스가 만들어진다면 결국 가장 조상격의 프로세스가 존재하기 마련이다.

이러한 프로세스들은 각자의 프로세스 아이디(pid)로써 구분할수 있으며 부모와 자식프로세스간의 통신으로는 signal이라는 매체를 사용하게 된다.

 

이 과정에서 부모프로세스가 자식프로세스보다 먼저 끝난다면(죽는다면) 남은 자식프로세스는 고아프로세스 라고 하며, 반대로 부모프로세스가 자식프로세스의 종료상태를 회수하지 못한상태에서 자식프로세스가 먼저 죽는다면 이를 좀비프로세스라고 한다. 자세한코드는 Linux programming에서 다루겠다.

 

 

 

 

2.쓰레드(Thread)

 

그렇다면 쓰레드란 무엇일까. 

결국 자식프로세스를 생성하게 되면 부모프로세스의 데이터정보를 모두 가져간다고 했다.

프로세스의 생성

 

하지만 쓰레드를 생성할시,

쓰레드 생성

 

이처럼 전역변수와 코드영역을 공유하고

고유의 스택만 생성해 가져가게 된다.

 

정리하자면, 

 

우리가 컴퓨터를 사용할때 게임을하며 음악을 들으며 인터넷브라우저를 켜놨다고 가정하자.

동시에 이러한 작업이 이루어질 수 있는 것은 CPU가 시간을 분할하여 CPU를 사용할 수 있는 제어권을 각각의 프로그램에게 한번씩 나누어주고 있기 때문이다.

보통 이 하나의 작업 즉, 운영체제에서 실행중인 하나의 프로그램을 프로세스라고 하며

작업이 여러 개 이루어진다는 것은 프로세스가 여러개가 동시에 동작하고 있다는 의미이다.

그리고 이처럼 두개 이상의 프로세스가 실행되는 것을 멀티프로세스 라고 하며 이 멀티프로세스를 실행하여 일을 처리하는 것을 멀티 태스킹이라고 한다.

쓰레드는 위에서 설명한 프로세스 내에서 실행되는 세부 작업의 단위이다. 여러개의 쓰레드가 모여 하나의 프로세스를

구성하며, 이 하나의 프로세스를 구성하는 여러개의 쓰레드를 멀티쓰레드라고 부른다.

스타크래프트 유닛들도 모두 멀티쓰레드로 구현된것..!

 

멀티쓰레드의 장점

 

Responsiveness(응답성)  may allow continued execution if part of process is blocked, especially important for user interfaces

Resource Sharing(자원공유)  threads share resources of process, easier than shared memory or message passing

Economy(절약성)  cheaper than process creation, thread switching lower overhead than context switching

Scalability(확장성)  process can take advantage of multicore architectures

 

 

또한 멀티쓰레드에사는 어떤 쓰레드가 먼저 실행이 될지는 아무도 알 수 없다.

 

 

 

프로세스와 쓰레드의 차이에 관해 정리된 블로그

 

 

프로세스와 스레드의 차이

기술 면접 단골손님 feat. 운영체제 | 프로세스와 스레드에 대해서 설명해주세요. 익숙한 질문입니다. 신입 개발자 면접 질문 목록에 빠지지 않고 등장하는 질문인데요. 아무리 쉽고 익숙한 질문

brunch.co.kr

 

 

면접에서 운영체제 질문을 받으면?

매일 진행하는 스터디의 2주차 주제는 운영체제 였는데 운영체제 내부의 다양한 기술적인 이야기는 스터디원들이 이야기 해줄 것 같아서 면접에서 물어볼 만한 os 질문들을 모아 봤다.

velog.io

 

 

 

 

 

쓰레드 동기화

 

 

 

운영체제 - deadlock과 starvation

교착상태(deadlocck)와 기아상태(Starvation) 교착상태란? 두 개 이상의 작업이 서로 상대방의 작업이 끝나기 만을 기다리고 있기 때문에, 다음 단계로 진행하지 못하는 상태 배치 처리 시스템에서는 �

velog.io

 

 

 

 

앞서 타이머 인터럽트로 인한 프로세스 이양이나, 입출력을 할때도 CPU의 낭비를 막기위해 준비큐에있는 프로세스에게 CPU를 할당해준다고 했다. 이와 같이 프로세스의 상태를 바꿔주는것을 문맥교환(Context Switch) 이라고 한다.

 

문맥교환을 하게되면, 원래 CPU를 보유하고 있던 프로세스는 프로그램 카운터 값등 프로세스의 문맥을 자신의 PCB에 저장하고 새롭게 CPU를 할당받을 프로세스는 예전에 저장했던 자신의 문맥을 PCB로부터 실제 하드웨어로 복원한다.

시스템콜이나 인터럽트로 인해 운영체제에게 CPU제어권이 넘어와 잠시 프로세스의 문맥일부를 PCB에 저장하는것은 문맥교환이라고 하진 않는다.(사용자모드에서 커널모드로 실행모드만 바뀔뿐)

 

문맥교환에 소요되는 시간은 실제로 시스템에게 유용한 시간은 아니다. 따라서 타이머세팅간격을 짧게해 문맥교환이 빈번히 일어난다면 프로그램성능이 떨어지고, 반대로 너무 크게 정하면 시분할시스템의 의미가 퇴색하게 된다. 고로 적절한 CPU 시간할당이 중요하다.

 

 

앞서 컴퓨터 시스템의 동작원리에 대해 간단히 알아보았는데,  여기서 인터럽트(Interrupt) 가 나왔다.

인터럽트의 동작원리는 간단히 말해 A라는 프로그램이 CPU를할당받아 명령을 수행하고 있는데, 인터럽트,즉 방해를 받아 A를 저장해놓은 후 일처리를 하고 다시 돌아와 A를 마저 수행하는 것이다. 이때 어디까지 일을 하고갔는지를 저장하기위해 운영체제는 고유의 자료구조를 가지고 있는데 우리는 이것을 프로세스제어블록, 즉 PCB(Process Control Block)이라 부른다.

 

인터럽트에는 하드웨어 인터럽트와 소프트웨어 인터럽트가 존재하는데,  일반적으로 인터럽트는 하드웨어 인터럽트, 즉, 하드웨어 컨트롤러가 CPU의 서비스를 요청하기위해 발생시키는 것을 의미한다.

이러한 인터럽트를 알아보기 전에 우리는 간단히 컴퓨터 시스템의 작종 개요를 알 필요가 있다.

 

흔히 CPU는 컴퓨터의 두뇌라고 불리지만, 인간의 뇌처럼 스스로 생각하고 판단하는 능력은 없다. 그저 계산하고, 처리할 뿐이다. 이때, CPU가 현재 수행해야 할 메모리 주소의 명령을 담고있는 레지스터를 '프로그램 카운터'라고 부른다.

한편 컴퓨터 동작이 CPU에 의해 이루어 지는것만은 아니다. 프로그램이 수행되는 중에 디스크에서 파일을 읽어오기도 하고, 키보드로부터 입력을 받거나 처리결과를 화면에 출력하기도 한다. 이러한 명령을 일반명려이 아닌 특권명령으로 분류한다. 이때, 사용자프로그램은 특권명령을 직접 수행할수는 없다! 따라서 운영체제에게 특권명령의 대행을 요청하게 된다.이것을 시스템 콜(System call) 이라고 하는 것이다.

 

결국 프로그램이 시스템콜을 하게되면 운영체제는 자신의 커널영역으로 들어가 시스템콜 처리코드를 수행하게 되고, 

만약 디스크에서 자료를 읽어오는 시스템 콜이라면, CPU가 컨트롤 레지스터를 세팅해 디스크 컨트롤러에게 디스크를 읽어오라는 명령을 내린다. 그러면 디스크 컨트롤러는 디스크로부터 데이터를 읽어와서 자신의 로컬 버퍼에 저장하게 된다. 이작업이 완료되면 디스크 컨트롤러가 CPU에게 인터럽트를 발생시켜 입출력이 완료되었음을 알린다. 이는 소프트웨어 인터럽트의 일종이다.

 

 

컴퓨터 시스템의 하드웨어 구조 및 프로그램이 메모리에 적재되는모습

 

 

프로그램이 아닌 주변 하드웨어가 CPU에게서비스를 요청할 때에도 비슷한 방식이다. CPU는 메모리 위치의 명령만 계속 수행하고 있으므로, 인터럽트를 사용하면 CPU에게 서비스를 요청할 수 있게 된다. 인터럽트를 발생시키기 위해 장치들은 인터럽트 라인(Interrupt Line)을 세팅하게 되고, CPU는 매번 명령을 수행한 직후 인터럽트 라인을 체크해 서비스 요청이 들어왔는지를 체크하게 된다. 인터럽트에는 다양한 종류가 있기 떄문에 각각의 인터럽트 발생 원인마다 라인을 다르게 해서 구분하게 된다. 인터럽트가 발생하면 CPU는 해당 인터럽트를 처리하기 위한 루틴을 가지고 있고, 그 처리 루틴에 따라 코드를 수행하게 된다.

 

특정 프로세스가 하나의 CPU를 독점하는 것을 막는 운영체제의 '타이머인터럽트'가 그 대표적인 예이다.

이 타이머 인터럽트는 하드웨어 장치로써, 일정시간을 세팅하게 되며 타이머 동작 이후에는 현재 프로세스를 회수해 다른 프로세스에게 이양하게 된다.

 

이렇듯 인터럽트는 넓은 의미에선 하드웨어 인터럽트와 트랩(trap)을 모두 포함한다.

트랩의 종류에는 예외상황과 시스템콜이 있는데, 

예외상황이란 허용되지않은 연산을 수행하려고 할때 자동적으로 발생하는것으로 운영체제는 예외상황이 발생했을때 CPU의 제어권을 획득해 해당상황에 대한 조치를 취한다.

0으로 나누는 연산, 자신의 주소공간을 넘는 메모리 참조등이 해당된다.

 

이러한 상황들은 모두 인터럽트 라인을 세팅하여 인터럽트를 발생시킨 후 제어권이 넘어가게 되므로 이들도 넓은 의미에서는 인터럽트의 범주이다. 단지, 인터럽트를 발생시키는 주체가 하드웨어가 아닌 소프트웨어 이므로 소프트웨어 인터럽트라고 부른다.

 

시스템 콜

 

<<인터럽트 관련 주요 용어>>

-인터럽트 벡터(Interrupt Vertor) : 여러가지 인터럽트에 대해 해당 이넡럽트 발생시 처리해야 할 루틴의 주소를 보관하고 있는 테이블

 

-인터럽트 핸들러(Interrupt Handler) : 실체 인터럽트를 처리하기 위한 루틴

 

 

<<사용자프로그램이 사용하는 함수>>

- 사용자 정의 함수 :  프로그래머가 직접 작성한 함수

- 라이브러리 함수 : 직접 작성하진 않았지만, 누군가 작성해 놓은 함수를 호출해 사용하는 경우

- 커널 함수 : 운영체제 커널의 코드에 정의된 함수(시스템 콜 함수, 인터럽트 처리함수 등이 있다)

 

printf 의 경우 라이브러리 함수이지만, 커널함수호출인 시스템콜을 동반한다.

프로세스란, 수행중인 프로그램을 뜻한다.

디스크에 실행파일형태로 존재하는 프로그램이 메모리에 올라가서 수행되기 시작하면 비로소 생명력을 갖는

프로세스가 되는 것이다.

 

시분할시스템의 프로세스 상태

 

프로세스의 상태는 실행(running), 준비(ready), 봉쇄(blocked,wait,sleep) 상태로 구분할 수 있다.

 

실행상태는 프로세스가 CPU를 보유하고 있는 상태이며, 일반적인 컴퓨터의 CPU가 1대로 가정하면 실행상태에 있는

프로세스는 매시점 하나뿐이다.

 

준비상태는 프로세스가 CPU만 보유하면 당장 명령을 실행할 수 있지만, 아직 CPU를 할당받지 못한 상태이다.

 

봉쇄상태는 프로세스에게 CPU를 주어도 당장 명령을 실행할 수 없는 상태를 말한다.

 

 

하나의 프로세스는 앞의 상태중 어느 한 상태에 머무르게 된다.

입출력을 요청한 프로세스의 상태변화가 어떻게 일어나는지 예를들어보자.

 

프로세스가 실행중에 입출력 요청을 받으면, 디스크에서 파일의 내용을 읽어오는 등의 명령이 포함될 수 있다.

하지만 이러한 작업은 CPU의 본연의 임무를 처리하는 속도에 비해 상대적으로 오랜시간이 걸리는 작업이기 때문에,

디스크입출력이 진행되는동안 CPU는 후속명령을 처리하지 못하고 아무것도 하지못하는 일명 낭비가되는 현상이 발생한다.

 

따라서 입출력을 하는 동안은, 이 프로세스는 CPU를 반환하게 되며 다음 디스크입출력 서비스를 기다리는 장치 큐(wait queue) 에가서 줄을서게되는데, 이때 프로세스는 봉쇄(Block) 상태가 된다.

 

그렇다면 반환된 CPU를 받는 프로세스가 있어야 하는데, 이는 준비큐(ready queue)에 줄서있는 프로세스들 중에 CPU스케쥴러가 적절한 프로세스를 하나 선정해서 CPU를 할당하게 된다.

이 준비큐에 있는 프로세스는 CPU를 휙득하면 곧장 명령을 수행할 수 있는 프로세스, 즉 준비(Ready)상태의 프로세스들이 존재한다.

 

그렇다면 아까 디스크 입출력을 요청하는동안 Block 되어버린 프로세스는 어떻게 되는 것일까.

이 프로세스는 디스크 입출력을 기다리는 장치 큐에 줄을 서 있다가, 원하는 데이터를 버퍼로 받아들인다면 '디스크 컨트롤러'가 CPU에게 인터럽트를 발생시켜 입출력 완료를 알리게 된다.

 

그렇게되면 CPU는 인터럽트를 확인하고, 그에 대응하는 루틴을 수행하게 된다.

이 루틴의 임무는 입출력이 완료된 프로세스를 장치 큐에서 빼내어 CPU를 기다리는 준비 큐에 넣어주고 프로세스의 상태를 준비상태로 바꾼후 장치의 로컬버퍼에 있는 내용을 메모리로 이동시키는 것이다.

자세한것은 인터럽트 포스팅에서 다룰 것이다.

 

경우에 따라서는 입출력을 완료한 프로세스가 원래 있던 인터럽트를 받은 프로세스의 자리를 차지하고 CPU를 할당받는 경우도 있는데, 이는 스케줄링과 관련이 있다.

'OS' 카테고리의 다른 글

[OS] 문맥교환(Context Switch)  (0) 2020.06.07
[OS] 인터럽트(Interrupt) 원리  (0) 2020.06.07
[OS] Linux, Mac(Darwin), Android  (0) 2020.06.06
[OS] 운영체제의 역사  (0) 2020.06.06
[OS] 운영체제(OS) 개요  (0) 2020.06.06