컴퓨터 세상의 정부(=government) 역할을 한다. 인적, 물적 자원들을 행정처리하는것 처럼
컴퓨터 자원을 컨트롤 타워 역할을 한다.
물론 기계적으로 보면 명령어를 해석하여 메모리에 올리고, 어떻게 연산하고 하는거는 전부 CPU의 몫이다.
그런데 말이다. 그 CPU를 다이렉트로 사용자 소프트웨어가 컨트롤해야되는 상황이라고 치자.
사용자마다 입출력장치의 레지스터 명령어가 다르고, 사용자마다 CPU연산은 다르면 어떻게 컨트롤할건데, 일반 응용프로그램이 대체 얼마나 무거워지고 개발자 죽어난다.
그래서 컨트롤 타워 역할을 알하서 하는 소프트웨어가 운영체제
컴퓨터 공학을 공부하는 이유... 만능 답안 결국 컴퓨터 세상의 문제해결을 위해서.
주기억 장치는 현재 실행중인 모든 프로세스가 다 올라오는 공간이다.
이는 운영체제에도 예외는 아님. 운영체제도 메모리에 올라와야 비로소 동작하는 것.
이렇게 운영체제같은 핵심 프로그램은 특수한 공간에 올라오는데 그 특수하게 지정된 공간 커널
영역이다.
운영체제의 모든 기능들이 다 커널에서 제공되는건 아니다. 커널외 사용자공간
에 적재된 기능도 존재하는 데 바로 사용자와 직접 상호작용
하기 위한 기능인 UI
기능이다.
이건 외우는게 아니다. 자연스러운 흐름이다. 사용자가 함부로 건들지 못하게 하기 위해 커널
에 적재해야하는 기능이 있는거고, 사용자가 건드려야하는 사용자 영역
에 적재헤야되는 기능이 있는것
UI는 크게 GUI
와 CLI
방식으로 나뉜다. 전자는 그래픽 인터페이스로 마우스나 터치로 클릭하여 반응하는거고, 후자는 커맨드라인이라는 명령어 입력을 직접하여 기능을 동작시키는 인터페이스
앞서 커널
은 사용자의 조작, 응용프로그램의 조작으로부터 안전하게 분리시키기위한 영역이라고 했다. 하지만, 적재만하고 전혀 사용하지 않으면 무슨 소용인가.
그래서 커널영역안의 코드기능을 사용하고자 할때 시스템 콜을 이용하여 운영체제에게 기능 요청을 하게된다.
이 때 시스템 호출을 통해 하는 것이 모드 전환
이다. 커널 모드
와 사용자 모드
두 가지 모드를 통칭하여 이중 모드라고 하고, 커널모드를 획득해야 비로소 커널 기능을 받아 사용할 수 있게 된다.
시스템 호출은 인터럽트 방식으로 동작한다. 인터럽트 체크는 새로운 클럭신호에 체크된다. 보내놓고 응답하여 처리하고 다시 돌아오고 방식으로 작동한다는 것.
CPU, 메모리, 입출력장치에 이르기까지 사실상 하드웨어를 컨트롤하기 위한 모든 기능은 전부 다 관리한다고 보면 된다. 하드웨어를 관리한다는것 자체가 바로 컴퓨터의 동작이다.
VM(=Virtual Machine)은 운영체제 위에 또 다른 운영체제 서비스를 구동시키는 것.
제2의 운영체제도 하드웨어가 있어야 돌아간다. CPU, Memory, 입출력
이걸 관리하는 놈은 제1의 운영체제이다.
따라서 제2의 운영체제도 응용프로그램마냥 계속해서 이중모드 컨트롤 인터럽트를 사이클을 반복하며 마치 자기가 컨트롤하고 있는듯이 동작하게 된다.
종류 | 시스템 호출 | 설명 |
---|---|---|
프로세스 관리 | fork() | 새 자식 프로세스 생성 |
exit() | 프로세스 종료 | |
execve() | 프로세스 실행 | |
---- | ---- | ---- |
파일 관리 | open() | 열기 |
close() | 닫기 | |
read() | 읽기 | |
write() | 쓰기 | |
stat() | 파일 정보 조회 | |
---- | ---- | ---- |
디렉터리 | mkdir() | 메이크 디렉터리 |
rmdir() | 리무브 디렉터리 | |
---- | ---- | ---- |
파일 시스템 관리 | mount() | 파일 시스템 마운트 |
umount() | 파일 시스템 언마운트 | |
프로세스: 각자 기능을 맡아 정해진 일을 수행하는 프로그램
실행중인 프로세스: 메모리 자원을 할당 받고, 각기 다른 사이클로 시스템 자원을 빨아먹어가며 돌아가는 프로세스들
확인방법: 유닉스는 ps명령어, 윈도우는 작업관리자
포그라운드 프로세스: foreground process
기능을 수행하는게 현재 관측되는 앞에 나와 기능하는 모든 프로세스
백그라운드 프로세스: background process
뒤에 숨어서 일을 수행중인 프로세스
데몬과 서비스: 백그라운드 프로세스 방식 중에서 사용자와 상호작용이 불가능하며, 주어진 상황따라 묵묵히 자기 일을 하는 프로세스
Process Control Block == 프로세스 제어 블록
프로세스와 관련한 정보들이 저장된 데이터 블록이다. 메모리에 적재된다.
프로세스의 탄생시간이나, 프로세스 아이디값, 프로세스의 메모리 주소, 필요한 입출력장치 등 동적으로 잘 바뀌지 않는 정보들이 프로세스 탄생시에 기입되기도 하지만,
PCB에는 시시각각 변하는 정보들도 여기에 기입된다. 이는 문맥교환
을 위한 필수적인 정보들이며, CPU가 인터럽트를 처리할때, 다른 프로세스들에 잠깐 들렸다가 올때 등등 실행중이던 프로세스가 정상 작동할 수 있게 하는 아주 중요한 핵심 동작 원리이다.
문맥에 따라 의미가 바뀌는 단어처럼. 프로세스도 현재 상태, 레지스터 값, 사용한 파일 등등 CPU입장에선 문맥이 바뀌고, 프로세스 입장에선 자기 자신 문맥을 보호하기위한 방법이 PCB에 싸그리 저장 때려 박는 방식인것
문맥교환
이미 위에 설명을 다 해버렸는데, CPU가 동시에 멀티 프로세스 작업을 하는 것 처럼 보이는 이유는 PCB에 문맥정보를 저장하고, 실시간으로 빠르게 문맥들을 교환해가며 모든 프로세스들을 컨트롤하기 때문이다.
중요한걸 빼먹었는데 PCB는 핵심적인 기능인 만큼 커널영역에 저장되어 있다. 응용프로그램이 함부로 바꾸지 못하게. 철저하게 운영체제가 관리
프로세스는 운영체제와 달리 사용자 영역
에 자리 잡는다. 이런 프로세스는 내부적으로 코드영역
, 데이터 영역
, 힙 영역
, 스택 영역
으로 나뉜다.
코드 영역: CPU가 실행할 명령어들의 집합
데이터 영역: 프로세스부터 사용할 데이터가 미리 적재되어 항시 참조가능한 데이터들의 집합
힙 영역: 프로그래머에 의해 상황따라 동적으로 변수를 만들고, 데이터를 누적한다면 바로 이 영역에 쌓여 올라간다
스택 영역: 힙영역과 거꾸로 아래로 누적되어 쌓여가는 구조이다. 동적으로 필요한 데이터들이 생겨나서 push되고 역할끝나면 바로 pop되어서 사라지는 영역. 주로 지금 호출되고 있는 함수의 지역변수, 매개변수, 함수주소 등이 그 예시. 호출되서 반환하면 뭐하겠어? 사라지겠지.
코드+데이터 = 정적 할당 영역
힙 + 스택 = 동적 할당 영역
생성상태
, 준비상태
, 실행상태
, 대기상태
, 종료상태
각각에 대한 설명
생성상태: 메모리에 올라가고 PCB 작성된 따끈한 상태
준비상태: CPU 사용준비 완료. 차례가 오길 기다려.
실행상태: CPU가 받아들여줬어. 열심히 작업을 막해
대기상태: CPU를 사용할 수 없는 상태. why? 일반적으론 입출력장치 문제인데, 입출력장치의 완료 신호를 기다리는 상태이다
종료상태: 찐 종료. 이 상태는 오래 있지 않다. 상태전환되자마자 메모리에서 아웃되며, 빠르게 리스트에서 지워짐
다이어그램
프로세스는 그냥 바닥에서 부터 평등하게 시작하는게 아니다. 프로세스를 호출한 녀석이 부모 프로세스가 되어 링크드 리스트 혹은 실제 프로그램의 함수호출 구조 마냥 부모 프로세스 자식 프로세스가 쌓여간다.
단순한 바탕화면에서 브라우저를 더블클릭하는 거 자체도 운영체제라는 부모 프로세스가 자식프로세스인 브라우저를 생성한거고
브라우저가 배너를 클릭하니, pc의 소프트웨어 런처가 실행될때에는 브라우저가 부모 프로세스가 되는 형태이다.
최초의 프로세스가 모두의 부모 프로세스가 되는 경우는 있지만, 최초의 프로세스를 제외한, 다른 모든 프로세스에 부모 프로세스가 없는 경우는 없다.
결론: 복제와 옷 갈아입기 방식을 사용한다.
부모 프로세스는 자기 자신을 복제품을 일단 만들고, 이후 자식 프로세스에 필요한 PCB, 코드영역 데이터영역을 채워가며 프로세스를 생성상태를 만들어낸다.
fork() :복제-> exec(): 덮어쓰기
스레드는 어휘적으로 실행의 흐름 단위이다.
어느 도메인에 걸쳐 있냐에 따라 CPU, 프로그램, 운영체제, 아니면 다른 분야 등등 에서 광범위하게 사용하는 용어임
여기서는 당연히 프로세스 즉 소프트웨어적인 관점에서의 스레드이다.
프로세스 내부적으로 만약 하나의 작업만을 한다면 굉자히 어.. 원시적이다. 하지만 지금 어플들의 광범위한 동시다발적 기능을 관찰하자.
지금 에디터에서 글을 쓰는 와중에도 커밋이 발생하고 있으며, 글자 수를 체크하고, 맞춤법을 검사하고 있다.. 이건 다 스레드 덕분인거다.
왜? 하나의 프로세스를 돌리고 있으니까. 그런데 작업은 여러개를 동시에 처리하고 있으니까.
이미 앞서 CPU는 한타이밍에 하나의 작업밖에 못한다고 배웠다. 그 말인 즉슨 동시 작업을 하는것 처럼 보이는 모든 행위는 무수히 빠른 속도로 스위칭하며 모든 프로세스를 한번씩 실행시켜주고 있기 때문이다.
이는 스레드에서도 같은 원리이다. 문맥교환이 일어나듯이 스레드도 스레드 문맥교환이 일어나고 있는 것이다.
그러면 PCB같은게 필요하겠네?
-> 그렇다. PCB같은게 있다. 이를 TCB
라고 한다.
이 TCB는 어디에 있는데?
-> 커널 영역에 존재하며, 당연히 PCB는 TCB를 링크하기 위한 주소값들을 전부 알고 있는 상태이다.
CPU는 프로세스들을 번갈아 가면서 실행시켜 모든 프로세스가 마치 동시에 실행중인것처럼 작동시킨다고 했다.
무슨 기준으로 어떻게 번갈아갈지를 결정하는 방법이 스케쥴링이고, 기본 토대를 하는 것이 프로세스의 우선순위 이다.
우선순위를 어떻게 부여할 것인가? 작업중인 프로세스를 끝까지 돌릴것인가 중간에 자원을 뺏을것인가 등 여러 고려법이 있다.
프로세스를 그냥 크게 나눠보면, CPU작업과, 입출력 작업으로 나눠볼수 있을것이다. CPU작업에는 메모리와 CPU 직접적인 작업이고, 입출력 작업은 키보드, 모니터, 스피커, 하드디스크 등 입출력 장치들의 작업이 완료되기를 기다리는 작업이 많다는것.
이를 CPU bound process
, I/O bound process
로 개념적으로 나눈다. 이렇게 개념적으로 나뉘었을때 우선순위가 높은건 일반적으로 I/O bound process 이다.
-> 왜? 입출력 바운드면 그만큼 CPU는 좀만 사용하고 바로 대기 상태를 자주 들린다는 소리이다. 이는 곧 우선순위를 높여놔야. 작업효율 증가를 의미한다.
더 잘게 들어가서 CPU를 사용해야하는 작업은 CPU burst
입출력은 I/O burst
라고 용어를 구분한다.
우선순위가 높다고 그저 바로 사용하게 하는 것은 아니다. 근본적으로 스케줄링 큐라는 개념이 존재한다. 우선순위에 의해 스케줄링큐의 순서가 마구 바뀌는 경우도 있고 아닌 경우도 있는데, 일단은 스케줄링 큐에서 줄을 서고, 순서에 맞게 CPU 자원을 사용하는 기회를 받는다고 생각.
선점형: preemptive scheduling
사용하고 있는 자원을 강제로 뺏는 방식. 특징. 시스템의 의도는 뺏어서 여러 프로세스들을 적절하게 실행시키기 위함이다. 부작용은 문맥교환이 자주일어남에 따른 오버헤드
비선점형: non preemptive scheduling
일단 사용하고 있으면 뺏지는 않는 방식. 시스템의 의도는 사용하고 있는 자원에 프로세스가 집중하여 빠르게 끝내고 다른 프로세스가 효율적으로 사용하게 하기 위함. 부작용은 프로세스 기회 불균형
First Come First Served : 선입선출과 비슷. 큐에 가장 어울리는 방식.
비선점형. 먼저 온 순서대로 처리됨.
만약 비효율적인 자원 점유시간으로 프로세스가 들어오게되면, 2클럭이면 끝나는 작업이 늦게 들어왔다고 100클럭을 기다려야 할 수도 있는 상황이 발생함. 이를 호위효과 convoy effect라고 함.
Shortest Job First: 일단 작업이 막 물밀려 오듯 들어올때 가장 작업 속도가 덜 들어가는 작업이 더 높은 우선순위를 받아서 스케쥴링 큐 앞쪽으로 이동되는 기법.
그렇다고해서 이미 작업중인걸 끊는 개념은 아니다. 즉 비선점형이다.
Round Robin : FCFS에 타임 슬라이스 개념이 적용됨. 점유가 길어져 타임슬라이스에 걸리게 되면, 해당 프로세스는 남은 작업을 PCB에 저장후 문맥교환이 일어나고 준비큐로 다시 들어가게 됨.
네트워크 처리에서 많이 보이는 방식이라고 한다
Shortest Remaining Time: 최소 잔여 시간 스케줄링. 최소 잔여시간을 가진 프로세스가 항상 우선순위를 높게 가져가는 시스템이다. 선점형 스케쥴링 방식이고, 먼저 들어온게 잔여시간이 길다면, 계속해서 물밀듯이 들어오는 짧은 작업들이 넘쳐난다면 해당 프로세스는 절대 기회를 받지 못한다. 실제 상황이라면 이런 상황이 10초이상 지속되는 상황이 나올정도로 너무나도 컴퓨터가 무리하고 잇다면 10초동안 해당 프로세스는 응답없음으로 작동하게 된다.
Priority Queing: 사실 우선순위는 따로 나눌 필요 없는 근본 그자체이다. 그 근본에대한 설명이다. 최소 시간도 아니고, 먼저 들어온것도 아니고, 암튼 운영체제에 의해서 무언가 어떤 요건에 의해 우선순위가 할당되기만 하면 우선순위 스케줄링 방식이다. 진짜 근본이다.
이런 방식에서 생각해봐야 될 것은 태생이 우선순위 번호가 높아서 후순위이고, 앞서 SRT마냥 최악의 조건이 겹쳐 작은 우선순위의 프로세스들이 물밀듯이 밀려온다면, 해당 프로세스는 멈추게된다. 이를 기아현상 starvation이라고 함.
이런 스타베이션을 해결하기 위해, Aging 에이징 개념이 추가되어 있다. 에이징이란 마치 나이를 먹듯 일정 시간 이상 큐에 있는 애들은 강제로 우선순위를 낮춰주어 새로 들어오는 애들에게 무한히 밀리는 현상을 방지해준다.
Multilevel Queue : 다단계 큐 스케줄링. 큐가 하나가 아니라, 우선순위 레벨에 따라 여러 큐를 두고 비슷한 레벨단위끼리 큐를 공유하는 방식이다.
이는 우선순위가 후순위로 밀리더라도 완전 뒤에 있지않고, 큐자체를 레벨에 따른 횟수 차이는 있겠으나 번갈아가며 실행시켜주기 때문에 후순위 큐도 빠르게 자원을 받을 수 있게 된다.
이 개념은 어떤 우선순위를 부여할지는 모르겠지만, 일단 우선순위 레벨에 따른 큐가 여러개 존재하는것 그자체로 MLQ 시스템이라 볼 수 있다.
Multilevel Feedback Queue: MLQ에 피드백이란 개념이 들어간다. 피드백이란 무엇인가? Aging 개념이 추가되어 후순위 레벨에 있는 작업은 더 높은 레벨의 큐로 이동시켜주고, 앞순위 레벨에 있던 작업은 실행되고나서 남은 작업은 레벨을 뒤로 밀어 자원을 덜받게 함으로써 자원을 순환시킨다.
설계가 가장 복잡해보이고 고려할게 많은데, 요즘 CPU는 이 방식에서 발전된 개념을 사용한다.