컴파일러가 컴파일 과정을 통해 컴퓨터가 이해할 수 있는 기계어로 번역하여 실행할 수 있는 파일을 만들게 되는데, 이러한 과정을 빌드라고 함. 이 파일은 CPU가 읽을 수 있는 이진코드로 이루어져 있음.
Compile
소스코드 전체를 기계어로 번역함.
Interpreted
소스코드를 한 줄씩 번역하면서 실행함.
Hybrid
소스코드 전체를 중간코드(바이트 코드)로 번역한 뒤 가상머신(VM)에서 한 줄씩 실행함.
전처리
전처리기에 의해 소스 코드의 주석을 제거하고 소스 코드에 포함된 매크로나 지시자같은 것을 포함시켜줌.
컴파일러
오류 처리, 코드 최적화 작업을 하며 어셈블리어로 변환함.
어셈블러
어셈블리어는 목적 코드로 변환됨.
링커
프로그램 내에 있는 라이브러리 함수 또는 다른 파일들과 목적 코드를 결합하여 실행 파일을 만듦.
사용자가 요청한 작업이 커널에 등록되고 PCB가 만들어져 프로세스가 만들어진 상태.
CPU를 할당받기 위해 기다리고 있는 상태, CPU만 주어지면 바로 실행할 준비가 된 상태.
CPU를 할당받아 실행중인 상태.
프로세스가 실행되다가 입출력 처리를 요청하거나, 바로 확보될 수 없는 자원을 요청하면 CPU를 양도하고 요청한 일이 완료되기를 기다림.
메모리 부족으로 일시 중단된 상태.
어떤 이벤트가 발생한 이후 기다리며 프로세스가 차단된 상태.
대기 중단 상태와 유사하며 중단된 상태에서 프로세스가 실행되려고 했지만 메모리 부족으로 일시 중단된 상태.
프로세스가 종료될 때 아주 잠시 거치는 상태로 모든 자원이 회수되고 PCB를 삭제함.
지역변수, 매개변수, 리턴값 등 잠시 사용되었다가 사라지는 데이터를 저장하는 영역임. 함수 호출시 할당되고 함수 반환시 소멸됨. 로드시 (컴파일 타임) 크기가 결정됨.
동적 데이터 영역으로 메모리 주소 값에 의해서만 참조되고 사용되는 영역임. 프로그램 동작시(런타임) 크기가 결정됨.
전역변수와 정적변수가 저장됨. 이 변수들은 프로그램이 시작될 때 할당되어 프로그램 종료시 소멸됨.
실행할 프로그램의 코드가 저장됨. CPU는 이 영역에서 명령어를 하나씩 가져와 처리하게 됨.
프로세스 제어 블록으로, 운영체제가 프로세스를 제어하기 위해 정보를 저장해놓는 곳으로 프로세스의 상태 정보를 저장하는 구조체임. 프로세스 생성시 PCB가 만들어지며 주기억장치에 저장되다가 프로세스가 완료되면 PCB도 함께 제거됨.
컨텍스트는 CPU, 메모리에서의 프로세스(스레드)의 상태를 의미함.
CPU/코어에서 실행중이던 프로세스(스레드)가 다른 프로세스(스레드)로 교체되는 것.
컨텍스트 스위칭이 필요한 이유는..
하지만! 필요하다고 해서 과도하게 많이 해버리면 CPU에 비해서 스레드가 너무 많이 생성되면서 오버헤드가 발생함!
컨텍스트 스위칭이 발생하는 경우는..
여러 프로세스가 순차적으로 아주 짧은 주기로 실행되고 있으나 우리가 느끼기에는 동시에 실행되는 것 같은 느낌을 주는데, 이러한 컨텍스트 스위칭은 바로 OS 커널이 수행을 해준다.
사실 컨텍스트 스위칭은 다른 프로세스끼리의 스위칭이 있고, 같은 프로세스의 스레드들끼리의 스위칭이 있는데,,, 두 스위칭 모두 커널 모드에서 실행되기에 커널로 통제권이 넘어가고 CPU의 레지스터 상태를 교체한다는 점에서 공통점을 가진다.
그러나 같은 프로세스안에서 스레드끼리 스위칭되는 경우에는 메모리 영역을 공유하고 있기 때문에 비교적 덜 번거로운 과정이다.
아래는 다른 프로세스끼리의 스위칭 과정이다.
기본적으로 두가지 매커니즘에 의해 수행된다.
1. CPU를 내어주는 프로세스의 상태를 그 프로세스 제어 블록(PCB)에 저장
2. CPU를 새롭게 얻는 프로세스의 상태를 PCB에서 읽어옴
좀 더 구체적으로 알아보면,
1. 현재 실행중인 프로세스 혹은 스레드의 context 백업(CPU 레지스터 값들이나 어디까지 실행되었는지에 대한 정보 등등)
2. CPU 캐시를 비움
3. TLB(Table Lookaside Buffer)를 비움
4. MMU(Memory Management Unit) 설정을 변경
와 같은 과정들이 필요하다. (같은 프로세스 내 스레드들끼리 변경에서는 메모리 주소 관련된 처리를 수행할 필요가 없기 때문에 1번만 수행해주면 된다!)
멀티프로세싱은 운영체제에서 하나의 응용 프로그램에 대해 동시에 여러 개의 프로세스를 실행할 수 있게 하는 기술을 말한다. 보통 하나의 프로그램 실행에 대해 하나의 프로세스가 메모리에 생성되지만, 부가적인 기능을 위해 여러개의 프로세스를 생성하는 것이다. 하나의 부모 프로세스가 여러 개의 자식 프로세스를 생성하는 방식이다.
멀티프로세싱을 사용하게 되면 하나의 프로세스에 문제가 생겨도 다른 프로세를 이용하여 처리할 수 있기에 신뢰성이 높다는 장점이 있다. 그러나 빈번한 Context Switching으로 인한 오버헤드가 발생하며 각 프로세스들은 독립적인 메모리 공간을 가지기에 결과적으로 메모리 사용량이 증가하고 자원 공유가 필요할 때에 복잡한 통신 기법인 IPC를 사용해야 한다.
운영체제 상에서 실행중인 프로세스 간에 정보를 주고받는 메커니즘을 말한다. 이를 위해 파이프, 소켓, 메세지 큐 등 다양한 방법이 사용된다. 그러나 IPC는 그 자체로 오버헤드가 발생하여 성능이 저하될 수 있고 코드의 복잡도를 증가시킬 수 있다.
익명 파이프
단방향 통신 채널로 오로지 부모 자식간에만 생성 가능하며, 양방향 통신을 위해서는 파이프가 2개 필요하다. read와 write가 기본적으로 block 모드로 작동한다.
네임드 파이프
양방향 통신을 지원하나 기본적으로 단방향으로 많이 사용되고 서로 다른 프로세스들이 파이프의 이름만 가지고 있다면 통신 가능하다.
메세지 큐
메모리를 사용한 파이프이며 구조체를 기반으로 통신한다. 여러 프로세스가 동시에 데이터를 다룰 수 있으나 커널에서 제공하기에 메모리 제한이 있을 수 있다.
공유 메모리
여러 프로세스에 동일한 메모리 블록에 대한 접근 권한이 부여되어 프로세스가 서로 통신할 수 있도록 공유 메모리를 생성해서 통신하는 것을 말한다.
소켓
동일한 컴퓨터의 다른 프로세스나 네트워크의 다른 컴퓨터로 네트워크 인터페이스를 통해 전송하는 데이터를 의미하며 TCP와 UDP가 있다.
멀티스레딩은 여러 코어에서 한 번에 여러 스레드를 처리하는 것이다. 즉 하나의 프로세스를 다수의 실행 단위로 구분해 자원을 공유하고 자원 생성 및 관리 중복을 줄인다.
스레드로 구현하게 되면 메모리 공간과 시스템 자원 소모를 줄일 수 있다. 또, 스레드 간의 데이터 공유와 같은 통신이 필요한 경우 별도의 자원 사용 없이도 전역 변수 공간, 힙 영역을 통해서 데이터를 주고받을 수 있어 캐시 메모리를 비울 필요가 없기에 시스템 처리량이 향상되고 프로그램 응답 시간이 단축될 수 있다.
그러나 스레드들이 공유하는 영역이 있기에 변수 및 자료 구조에 신경써야한다는 단점도 있다. 동기화 작업을 통해서 작업 처리 순서와 공유 자원의 접근을 컨트롤해야만 하고 이때문에 과도한 락으로 인한 병목 현상이 발생할 가능성이 높다. 또 스레드는 하나의 프로세스 안에서 동작하기에 하나의 스레드가 죽으면 전체 프로세스에 영향을 끼치게 된다.
프로세스 동기화란 여러 프로세스가 공유하는 자원의 일관성을 유지하는 것이다. 자원에 동시에 접근할 때에는 자료의 일관성을 해칠 가능성이 있다.
멀티스레드 환경에서 여러 스레드가 동시에 실행될 때 2개 이상의 스레드가 동일한 데이터에 접근하고자 하는 것을 경쟁 상태라고 한다. 그래서 우리는 하나의 스레드가 조작하고 있는 공유자원(변수, 데이터)를 다른 스레드가 조작하지 못하도록 통제가 필요한데, 이 통제가 필요한 영역을 바로 임계 영역이라고 한다.
임계 영역의 조건
임계 영역 구현 방법
뮤텍스
프로세스나 스레드가 공유 자원을 lock을 통해 잠그고 사용하며 사용 후에는 unlock을 통해 잠금 해제하는 방식.
세마포어
일반화된 뮤텍스로 간단한 정수 값과 두 가지 함수 wait와 signal을 통해 공유 자원에 대한 접근을 처리함. wait은 자신의 차례까지 기다리는 함수이며 signal은 다음 프로세스로 순서를 넘겨주는 함수임.
바이너리 세마포어
0과 1의 두 가지 값만 가질 수 있는 세마포어로 뮤텍스와 유사하나 뮤텍스는 잠금을 기반으로 상호배제가 일어나는 잠금 메커니즘이고 세마포어는 신호를 기반으로 상호 배제가 일어나는 신호 메커니즘임.
모니터
둘 이상의 스레드나 프로세스가 공유 자원에 안전하게 접근할 수 있도록 공유 자원을 숨기고 해당 접근에 대해 인터페이스만 제공함. 모니터큐를 통해 공유 자원에 대한 작업들을 순차적으로 처리함.
교착 상태는 일련의 프로세스들이 서로가 가진 자원을 기다리며 block되어 더 이상 진행이 될 수 없는 상태를 의미한다.
위의 사진처럼 시스템 자원에 대한 요구가 엉킨 상태로 두 프로세스가 사용하는 자원을 서로 기다리고 있을 때 발생한다.
교착상태 회피
교착상태가 발생하는 조건인지 확인하면서 적절히 회피하는 방법임. 안전 상태를 유지하도록 안전 순서열인지 검사하면서 자원을 할당함. 안전 순서열을 찾아내는 대표적인 알고리즘으로는 은행원 알고리즘이 있음.
교착상태 탐지 및 회복
교착상태의 발생을 인정하고 사후에 조치하는 방법임. 프로세스가 자원을 요구하면 우선 할당하며, 교착상태가 탐지되면 이를 회복하는 알고리즘을 사용함.
교착상태를 회복하는 방식에는 선점을 통한 회복과 프로세스의 강제 종료를 통한 회복이 있음. 선점을 통한 회복은 교착상태가 회복될 때까지 한 프로세스에게 자원을 몰아주는 방법이고, 프로세스의 강제 종료를 통한 회복은 교착상태에 있는 모든 프로세스를 강제 종료하거나 교착상태가 해결될 때까지 한 프로세스씩 강제로 종료하는 방법임.
교착상태 무시
교착상태를 무시하고 특별한 조치를 취하지 않는 방법임. 타조 알고리즘이라고도 하며 교착상태의 발생 확률이 낮은 상황에서 효율적인 방법임.
https://velog.io/@mingadinga_1234/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EB%9E%80-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%9D%98-%EC%83%81%ED%83%9C
https://st-lab.tistory.com/176
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
https://jwprogramming.tistory.com/16
https://velog.io/@nnnyeong/OS-Context-Switching-PCB-Process-Control-Block
https://s7won.tistory.com/11
https://velog.io/@kimunche/%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8-%EC%8A%A4%EC%9C%84%EC%B9%ADcontext-switching
https://hello-judy-world.tistory.com/191
https://iambeginnerdeveloper.tistory.com/186
https://inpa.tistory.com/entry/%F0%9F%91%A9%E2%80%8D%F0%9F%92%BB-multi-process-multi-thread
https://sete3683.tistory.com/60
https://eunsolsblog.tistory.com/entry/%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%8F%99%EA%B8%B0%ED%99%94
https://velog.io/@zioo/Deadlock%EA%B5%90%EC%B0%A9-%EC%83%81%ED%83%9C%EC%9D%98-%EA%B0%9C%EB%85%90%EA%B3%BC-%EB%B0%9C%EC%83%9D-%EC%9B%90%EC%9D%B8
https://www.robotstory.co.kr/raspberry/?vid=150