시스템 프로그래밍
1장 컴퓨터 구조에 대한 첫 번째 이야기
1 시스템 프로그래밍의 이해와 접근
시스템 프로그래밍이란?
시스템 프로그램
컴퓨터 시스템을 동작시키는 프로그램
시스템 프로그램이란 하드웨어를 사용할 수 있도록 도와주는 프로그램이라고도 할 수 있다.
컴퓨터를 동작시키기 위한 프로그램에는 Window, UNIX와 같은 운영체제들이 있다.
시스템 프로그램으로 프로그램을 개발하는 것을 시스템 프로그래밍이라고 한다.
2 컴퓨터 하드웨어의 구성
CPU (Centeral Precessing Unit) : 중앙처리장치, 컴퓨터의 머리
정의 : 나중에 자세히, 컴퓨터 프로그램 실행에서 핵심적 역하릉ㄹ 담당, 연산을 담당
메인 메모리(Main Memroy) RAM
정의 : 컴파일이 완료된 프로그램 코드가 올라가서 실행되는 영역이다.
목적 : 프로그램 실행을 위해 존재하는 메모리이다.
입 출력 버스(Input/Output Bus) : 고속도로
정의 : 컴퓨터를 구성하는 구성요소 사이에서 데이터를 주고 받기 위해 사용되는 경로이다.
목적 : 컴퓨터 구송 요소 사이 데이터를 주고 받기 위해 사용된다(통로 역할로)
특징 : 주고받는 데이터의 종류와 역할에 따라 버스가 구분된다. (어드레스, 데이터, 컨트롤)
구분되는 버스의 역할에 주의하자
버스 시스템 : 데이터를 이동하는 데 있어서 사용되는 전송 경로
데이터 버스 : 데이터를 이동하기 위한 버스
어드레스 버스 : 주소값을 이동하기 위해 필요한 버스
컨트롤 버스 : 사인을 주고받는 용도로 사용되는 버스 (사인? 데이터가 오고 가는 구분이 필요)
3 CPU에 대한 이해
ALU(Arithmetic Logic Unit)
정의 : CPU에서 실제 연산을 담당하는 블록이다.
목적 : 기본적인 연산(산술 연산, 논리 연산)을 담당한다.
컨트롤 유닛(Control Unit)
정의 : 명령어를 해석하는 영역이다.
목적 : CPU가 처리할 명렁어를 해석하는 역할을 담당한다.
레지스터 (Register Set)
정의 : CPU 내부에서 임시 데이터를 저장하는 작은 메모리 공간이다.
목적 : CPU 내부에서 임시적으로 데이터를 저장하기 위해서 레지스터를 사용한다.
버스 인터페이스(Bus Interface)
정의 : I/O 버스와 CPU(하드, 그래픽 카드 등에도 필요하긴 함)를 연결시키는 인터페이스 장치
목적 : CPU와 I/O 버스 사이 통신이 가능하게 하는 장치이다.
I/O 버스의 통신방식을 알고 있으므로 CPU와의 데이터 전송이 가능하게 하는 것이다.
클럭 신호(Clock Pulse)
정의 : 클럭 발생기에 의해 발생되는 신호이다.
목적 : 클럭 신호에 맞춰 CPU가 작동된다.
특징 : CPU의 구성요소는 아니다.
하지만 CPU 구성요소에 제공되어야 하는 신호로 중요한 의미를 지닌다.
가장 느린 장치의 장단에 맞춰 일한다.
4 프로그램의 실행 과정
단계 1 전처리기에 의한 치환 작업
소스코드를 적절히 변경하는 작업
단계 2 컴파일러에 의한 번역
컴파일러에 의 해 어셈블리 코드로 번역되는 단계
어셈블리코드란 CPU에게 일을 시키기위한 명령어들로 만들어진 프로그램 코드이다.
단계 3 어셈블러에 의한 바이너리 코드 생성
어셈블러 어셈블리 코드를 CPU가 이해할 수 있는 바이너리 코드로 바꾸어주는 프로그램
단계 4 ㄹ잉커에 의한 연결과 결합
프로그램 실행 3단계
Fetch : 메모리 상에 존재하는 ㅁ여령어를 CPU로 가져오는 작업이다.
Decode : CPU로 가져다놓은 명령어를 해석하는 단계이다.
ㅇExecution : 해석된 명령어를 CPU가 실행하는 단계이다.
여기까지 공부하면 exe파일 생성과정과 프로그램 실행 3단계를 이어서 설명할 줄 알아야한다.
exe파일 생성과정을 통해 만들어진 바이너리로 이루어진 코드가 램에 올라감.
Fetch 과정을 통해 램에 있는 코드가 CPU(레지스터)에 임시 저장됨
Decode 과정을 통해 컨트롤 유닛이 레지스터에 올라간 코드를 해석함.
Execution 과정을 통해 해석된 코드를 ALU가 실행시킴.
이런식으로 말이야.
4장 컴퓨터 구조에 대한 두 번째 이야기
1 컴퓨터 구조의 접근 방법
RISC vs CISC
명령어의 복잡도의 차이가 기준이지
CISC : Complex Instruction Set Computer : 복잡한 명령어 체계를 가지는 컴퓨터
명령어의 수가 많다. 따라서 명령어의 길이가 일정하지 않아 이를 처리하는 과정 역시 제각각이다.
:간단한 명령어 체계를 가지는 컴퓨터
전체 명령어중 주로 사용하는 명령어가 10%밖에 되지 않는 데소 착안한 구조이다.
자주 사용하지 않는 90%이ㅣ상의 명령어를 위해 CPU를 복잡하게 디자인하는 것보다 명령어 수를 줄이고 길이를 일정하게 디자인하는 효율적이라고 판단하여 탄생한 것.
명령어의 길이가동일하여 명령어를 처리하는 과정이 일정화되어있으므로 이점이 있다.
3 Direct 모드와 Indirect모드 (Direct Addressing, Indirect Addressing)
레지스터 디자인 방법의 문제점.
하나의 명령어에 여러 정보 (명령어, 레지스터 정보, 연산할 수 등)을 담다보니 표현하는 데이터 크기에 제한이 따른다는 문제가 발생할 수 있다. 레지스터의 수나 연산할 수의 범위
Direct addressing mode
우리가 지금까지 언급한 메모리 접근방법을 Direct 모드라고 한다. 램의 주소에 값을 직접 넣어 레지스터로 값을 로드하는 방식이다.
이 방법을 통해서는 메모리의 모든 영역에 대한 접근이 불가능하다. 왜냐? 할당된 비트 수 안에서 표현 가능한 범위의 메모리 영역만 접근 가능하기 때문이다. 무슨말이야
Indirect addressing mode
Direct 모드가 가진 단점을 해결하기 위해 등장.
램의 주소에 주소값을 넣어 해당 주소에 접근, 참조한 값을 레지스터로 로드하는 방식이다.
주소값의 범위가 넓다면.. 레지스터를 참조하여 해당 레지스터에 들어있는 값을 주소값으로 사용하는 방법을 쓰면 더 넓은 주소값을 사용할 수 있다.
5장 프로세스의 생성과 소멸
1 프로세스의 이해
프로세스
정의 : 실행 중에 있는 프로그램이다.
2 프로세스의 스케줄링과 상태 변화
스케줄링
정의 : 프로세스의CPU 할당 순서 및 방법을 결정 짓는 일을 말한다.
왜? 동시에 여러 프로세스를 실행시켜야 하지만 CPU는 하나이므로 한 순간에 하나의 프로그램만 실행 가능하다. CPU가 여러 개의 프로세스를 번갈아 가면서 실행한다면 사용자는 동시에 여러 프로그램을 실행시키는 것처럼 느끼게 된다. 멀티 프로세스는 이처럼 여러 개의 프로세스들이 CPU할당 시간을 나누기 때문에 가능한 것이다.
스케줄링 알고리즘
정의 : 스케줄링에 사용되는 알고리즘이다. 프로세스의 CPU 할당 순서 및 방법을 결정지을 때 사용하는 알고리즘이인 것이다.
스케쥴러 : 스케줄링 알고리즘을 적용하여 실제로 프로세스를 관리하는 운영체제 요소를 말한다. (소프트웨어이다)
프로세스의 상태 변화
프로세스 생성 : 프로세스는 생성과 동시에 Ready 상태로 들어간다.
Ready 상태에 이쓴 프로세스는 CPU에 의해 실행되기를 희망하는 상태이다.
(프로세스가 실행되지는 않고있으나 스케줄러에의해 선택되어 당장이라도 실행 가능한 상태)
Ready 상태에 있는 프로세스는 스케줄러에 의해 관리되는 프로세스이다.
스케줄러가 스케줄링 알고리즘을 기반으로 우선순위가 높은 프로세스를 선정하면 해당 프로세스는 Running 상태가 되어 실행된다.
프로세스들은 생성 시 중요도에 따라 우선순위가 매겨진다.
Running 상태에서는 프로세스에 따라 ready가 될 수도 blocked가 될 수도 있다.
프로세스가 입출력을 실행한다면 blocked 상태가되고, 아직 일이 안끝났는데 다른 우선순위 높은 프로세스가 등장한다면 잠시 그 프로세스를 실행하고 바로 다시 실행 가능하도록 ready상태에서 잠시 대기할 수도 있는 것이다.
Blocked 상태 : 실행 중인 프로세스기 실행을 멈추는 상태, 스케줄러에 의 해 선택될 수 없는 상태이다 (ready와의 차이점 둘 다 프로세스가 실행되지 않는 상태임)
(프로세스가 실행되지 않고 있으며 스케줄러에 의해 선택될 수 없는 상태 : 따라서 입 출력이 완료된 프로세스는 ready상태를 거쳐 running 상태로 변화한다.)
일반적으로 데이터 입출력과 관련된 일을 하는 경우 이러한 상태가 된다. 프로그램 실행의 상당 시간을 데이터 입출력에 소모하고 스케쥴러는 이러한 비 우선적인 일을 수행하고 있는 프로세스는 Blocked 상태로 만들고, Ready에 있는 프로세스 중 우선순위 높은 프로세스를 Running 상태로 변경한다.
3 컨텍스트 스위칭(Context Switching)
멀티 프로세스 환경에서 프로세스를 교체함으로써 한번에 여러 개의 프로세스를 동시에 실행시키는 것처럼 보인다는 장점을 봤다. 하지만… 단점또한 존재한다. 실행중인 프로세스를 변경하는 일은 시스템 부하를 일으킨다는 사실이다. “CPU 내에 존재하는 레지스터들은 현재 실항 중에 있는 프로세스 관련 데이터들로 채워진다.” 프로세스를 교체하려면 레지스터 역시 교체해줘야하는 번거로움이 있다는 것이다. 즉, 프로세스 교체가 일어나면 레지스터에 있는 데이터는 RAM으로, RAM에 있는 데이터(실행될 프로세스와 관련)는 레지스터로 옮겨진다. 이러한 작업을 ‘컨텍스트 스위칭’이라고 한다. “실행되는 프로ㅓ세스의 변경과정에서 발생하는 컨텍스트 스위칭은 시스템에 많은 부담을 준다” 레지스터 개수가 많은 시스템일수록 프로세스별로 관리되야아할 데이터 종류가 많을수록 이러한 부담은 커진다. 우리는 멀티 프로세스 운영체제의 단점이 컨텍스트 스위칭에 의한 부담이다라고 할 수 있겠다.
4 프로세스의 생성
CreateProcess 함수를 통해 프로세스를 생성. 함수를 호출하는 프로세스를 부모 프로세스, 함수에 의해 호출된 프로세스를 자식 프로세스라고 함.
이후 생성과 소멸 등 사용방법에 대한 설명은 Pass했다.
6장 커널 오브젝트와 오브젝트 핸들
1 커널 오브젝트에 대한 이해
ㄹ커널 : 컴퓨터를 운옇나는 데 있어서 중심이 되는 운영체제 핵심 부분이다. 일반적으로 커널이라는 용어와 운영체제라는 용어는 같은 의미로 사용된다.
커널 오브젝트 : 커널에서 관리하는 중용한 정보를 담아둔 데이터 블록이다.
Window 운영체제는 프로세스, 쓰레드 혹은 파일과 같은 리소스들을 원활히 관리하ㅏ기 위해 필요한 정보를 저장해야 한다. 이때 데이터를 저장하는 메모리 블록을 가리켜 커널 오브젝트라고 한다.
중요한 정보? 프로세스 정보를 관리하는 구조체 등( 운영체제가 프로세스들의 상태정보와 우선순위 등을 알고있어야 프로세스 상태를 관리할 수 있다), 프로세스 뿐만 아니라 프로그램 흐름을 구성하는 쓰레드를 생성할 때에도 IPC를 위해 사요되는 파ㅇ이프나 멤일 슬롯을 생성할 때에도 커널 오브젝트를 생성해서 필요한 정보를 채우기도 한다. 파일을 생성시에도 커널오브젝트가 생성된다.
커널 오브젝트는 프로그래머가 직접 조작할 수 없다. 시스템 함수 호출에 의해 간접적으로 조작하는 것이다. 실제 조작은 Window 운영체제가 수행한다.
안정성을 위해서이다. 프로세스를 관리하는 정보인 커널 오브젝트에 직접적인 조작이 이루어진다면 시스템 안정성이 떨어질 수 있기 때문이다.
커널 오브젝트 핸들 : 커널 오브젝트에 할당되는 숫자이다. 시스템 함수로 프로세스의 우선순위 등을 간접 조작하고자 할 때 핸들을 전달하는 방법을 사용한다.
주의점 함수가 호출되어 실행되는 중간에는 절대로 CPU의 할당 시간을 다른 프로세스에게 넘겨주면 안된다. 함수호출이 완료되지 않고 넘어가기 때문…
2. 커널 오브젝트와 핸들의 종속 관계
“커널 오브젝트는 Windows 운영체제에 종속적이다” 왜? 커널 오브젝트는 프로세스에 종속적인 것이 아니라 운영체제에 종속적인 관계로… 커널 오브젝트의 소멸 시점은 운영체제에 의해 결정된다. 추가로 커널 오브젝트의 생성 역시 운영체제가 관리한다 (사용하는 함수에서 프로세스 생성하면 커널 오브젝트도 생성되어 프로세스가 생성하는 것처럼 보이는 것 뿐이다)
커널 오브젝트는 프로세스에 종속적인 것이 아니라 운영 체제에 종속적인 관계이다. 따라서 여러프로세스들은 커널 오브젝트에 간접적으로 접근할 수 있다. ( 커널 오브젝트는 여러 프록세스에 의해 접근 가능해)
- 커널 오브젝트 공유 예시. 부모 프로세스가 자식 프로세스의 커널 오브젝트에 접근하여 그 자식 프로세스의 우선순위를 낮춘다. ( 자식 프로세스의 커널 오브젝트에 여러 프로세스가 접근)
l 커널 오브젝트는 운영체제에 종속적. 따라서 하나의 커널 오브젝트에 여러 프로세스가 접근할 수 있으며, 프로세스가 소멸된다고 해서 해당 프로세스의 커널 오브젝트가 자동으로 소멸되는 것이 아니다.
핸들은 운영체제에 종속적이지 않고 프로세스에 종속적이다.
프로세스 핸들 : 프로세스 커널의 오브젝트를 가리키기(구분짓기)위 한 것
프로세스 ID는 프로세스 자체를 구분짓기 위한 것
종료코드 : return 문에 의해 반환되는 값처럼 제대료 종료가 되었는지, 혹은 특정 문제가 있어서 종료가 안되었는지 알리기 위해 사용하는 코드를 말한다. 프로세스의 종료코드는 해당 프로세스의 커널 오브젝트에 저장된다. 자식 프로세스의 종료코드는 자식 프로세스의 커널 오브젝트에 저장된다. (만약 자식 프로세스가 종료되면서 자식 프로세스의 커널 오브젝트도 동시에 소멸된다면… 부모 프로세스는 자식 프로세스의 종료코드를 얻을 수 있는 방법이 없다. 따라서 프로세스의 종료와 커널 오브젝트의 소멸은 동시에 이루어질 수 없는 것이다.)
Window 운영체제는 커널 오브젝트를 참조하는 대상이 하나도 없을 때 소멸시킨다. (레퍼런스 카운트 방식인 것이다.
7장 프로세스간 통신(IPC) 1
1. 프로세스간 통신 IPC의 의미
IPC : Inter Process Communication 프로세스 사이의 통신이라는 뜻이다. 즉 둘 이상의 프로세스가 데이터를 주고받는 행위이다.
모든 운영체제들은 프로세스가 자신에게 할당된 메모리 공간 이외의 영역에 접근하는 것을 허용하지 않는다.(안전성을 이유로) -> IPC를 위해서는 프로세스 외 다른 무언가가 필요하다.
2. 메일슬롯 방식의 IPC
메일슬롯방식 : 메일 슬롯이라는 우체통을 이용하여 프로세스간 데이터를 송수신한다.
데이터를 수신하는 프ㅗ로세스 Receiver가 멩리 슬롯을 생성한다.
특징
할다된 주소를 기반을 통신하므로 네트워크만 연결되어 있따면 서로 관계 없는 프로세스 사이에서도 통신이 가능하다.
단방향 통신이다 ( 쌍방향으로 이용하기 위해서는 각각 메일슬롯 생성이 필요하다)
브로드캐스팅 방식의 통신을 지원한다.
3. 커널 오브젝트의 상태
커널 오브젝트는 두 가지 상태를 지닌다. 리소스에 특정 상황이 발생되었음을 알리기 위한 용도로 사용된다.
Signaled 상태 (신호를 받은 상태) 프로세스가 종료되면 Window 운영체제에 의해 자동으로 Signaled 상태가 된다.
Non_Signaled 상태 (신호를 받지 않는 상태) : 프로세스가 생성되면 Non_Signaled 상태에 놓이고 프로세스가 종료되면 Singnaled 상태로 변경된다.
즉 프로세스가 실행중인지 여부를 알 수 있는 것이다.
상태가 존재하는 이유?
커널 오브젝트의 상태는 리소스에 특정 상황이 발생함을 알려주기 위함이다.
최초에 커널 오브젝트가 생성되면 커널 오브젝트 상태는 Non_signaled. 종료되면 signale.
프로세스를 기준으로… 프로세스가 non_signaled 상랭라면 프로세스가 실행중이라는 것이다.
커널 오브젝트가 생성되면 자동으로 non_singed 상태가 된다 (실행중이라는것이지) 즉 커널 오브젝트 디폴트 상태는 non_signaled이다. 프로세스가 생성된 당시는 실행중일 것이기 때문이다.
WaitForSingleObject 함수 (프로세스가 현재 실행중인지 알 수 있음)
이 함수를 통해 자식 프로세스가 signaed(실행종료)상태라면 함수는 바로리턴
Non_signled(실행중)이라면 함수는 블로킹상태가 된다(블로킹?)
즉 이 함수는 커널의 상태를 확인하는 기능도 있으나… signaled(실행중)상태가 되기를 기다리는 기능이 더 크다.
8장 프로세스간 통신(IPC) 2
2. 파이프 방식의 IPC
이름 없는 파이프 Anonymous Pipe
단방향 통신방식이다.
파이프를 통해서 생성된 핸들을 기반으로 통신하기에 프로세스 사이 관계가 있어야한다.
이름 있는 파이프 Named Pipe
주소 정보가 있어 관계없는 프로세스들 사이에서도 통신이 가능하며 양방향 통신을 지원한다.
메일슬롯과 유사하다. 차이점은 브로드캐스트 방식을 지원하지 않고 양방향 통신을 지원한다는 점이다.
9장 스케줄링 알고리즘과 우선순위
1. 프로세스의 스케줄링( Scheduling)
RTOS Real time OS
OS vs RTOS
응답속도 : RTOS의 응답속도가 일반 OS보다 빠르다. 사용하는 목적이 구체적이고 제한적이다 보니 단순하게 디자인 되었기 때문이다. 즉 가벼워서 더 빠른 것이다.
OS : d범용적인 사용을 위해 디자인
RTOS : 사용하는 영역이 제한되어 있다.
Hard RTOS vs Soft RTOS
Hard RTOS : 데드라인을 중요시한다.일정 시간 안에 반드시 처리해야 하며 시간이 지난 후 결과 값은 정확해도 소용이 없는 경우 사용한다. (군사장비나 비행기)
Soft RTOS
시간 안에 처리하면 좋지만 그러지 못하더라도 약간의 시간이 경과한 후의 값도 인정한다.
Preemptive OS vs Non_Preemptive OS (선점형 OS vs 비선점형 OS)
프로세스의 실행을 다른 프로세스로 넘기는 방식에 따라서 선점형 OS와 비선점형 OS를 구분한다.
비선점형 OS
현재 실행 중인 프로세스보다 높은 우선순위의 프로세스가 4등장한다고 해서 실행 대상을 바로 변경하지 않는다. 현재 실행중인 프로세스가 명시적으로 CPU를 양보하거나, 블로킹 상태에 놓일 때까지 기다린다.
문제점 : Interactive한 프로그램 구현 시 프ㅍ로그래머 의존도가 높아지는 문제점이 발생할 수 있다. 프로그래머의 프로그램이 CPU를 독차지 하지 않도록 신경 써서 ㅍ ㅡ로그래밍 해야한다.
선점형 OS
실행중인 프로세스보다 높은 우선순위의 프로세스가 등장하면 스케줄러에 의한 실행순서 조징이 가해지는 OS이다. 따라서 비교적 스케줄러가 하는 일이 많다는 특징이 있다.
이러한 특징은 멀티 프로세스 기반 OS에 적합하다. 스케줄러에 의해 실행순서가 조정되는 것이므로 프로그래머의 의존도가 낮기 때문이다.
오늘날 대부분의 OS는 선점형 OS이다.
우선순위 스케줄링 알고리즘
우선순위 스케줄링 알고리즘이란 각각의 프로세스마다 우선순위를 부여해서 우선순위가 높은 프로세스를 먼저 실행시키는 방식이다.
라운드 로빈 스케줄링 알고리즘
우선순위가 동일한 프로세스들이 있는 경우라면?
이러한 경우 형평성을 위해 정해진 시간 간격만큼 실행하고 우서ㅓㄴ순위가 동일한 다른 프로세스에게 CPU할당을 넘겨주는 방식이다. 타임 슬라이스를 기준으로 CPU 할당을 넘긴다.
퀸텀 or Time Slice : 실행의 최소 단위 시간 간격이다.
정리하자면 Window는 우선순위 기반과 라운드 로빈 기반 알고리즘을 혼용하여 선점형 운영체제의 특성을 나타내도록 디자인된 운영체제이다.!!!!!!
이러한 Window 운영체제에서 스케줄러가 동작하는 시점은
1. 매 타임 슬라이스마다 동작 (동일한 우선순위의 프로세스가 있다면 타임 슬라이스 기준으로 프로세스를 교체해아야 한다.
2. 프로세스가 생성 및 소멸될 때 동작 ( 새로운 프로세스가 등장하거나 없어지면 우선순위를 비교해줘야한다.
3. 실행중인 프로세스가 블로킹 상태에 놓일 때 동작 ( 실행할 프로세스를 찾기 위해 동작)
Priority Inversion
10장 컴퓨터 구조에 대한 세 번째 이야기
1. 절차적 함수 호출(Procedure Call) 지원 CPU 모델
스택 프레임 : 함수 호출 과정에서 할당되는 메모리 블록을 말한다.
메모리 구조적 특징이 스택과 동일하다. (가장 먼저 쌓인 메모리가 가장 나중에 반환된다.
스택 구조처럼 메모리가 쌓이고 함수 호출이 완료되면 해당 함수에서 쌓였던 스택 프레임 메모리는 모두 반환되어 더 이상 접근할 수 없게 된다.
Sp 레지스터 (Stack Pointer)
목적 : 스택 프레임의 현재 위치를 저장하는 레지스터이다.
함수가 종료될 때 얼마만큼 반환할지 sp레지스터만으로는 모르기 때문에 프레임 포인터 레지스터에게 데이터를 전달받아야한다.
스택 프레임에 데이터를 쌓으려면 스택의 어느 위치까지 데이터를 저장했는지 기억해야한다. (스택은 쌓아올라지는 구조이므로) 이를 위해 CPU내에 sp라는 이름의 레지스터가 존재한다.
프레임 포인터 레지스터 (Frame Pointer)
함수가 새로 호출되면 sp 레지스터가 가리키는 주소를 fp 레지스터에 담는다.
함수가 반환되면 sp 레지스터는 fp 레지스터에 기록된 위치로 돌아가면 현재 위치로 갈 수 있다.
함수가 중첩된다면 fp레지스터에 기록된 주소를 잃어버리게 되므로…. 덮어쓰기전에 stack에 fp 레지스텅의 주소를 저장한다. (stack에 함수간 경계로 fp 레지스터의 이전값이 생성되는 것이다 최산값은 fp 레지스터 자체가 가지고 있고)
2. 함수 호출 인자의 전달과 PUSH & POP 명령어 디자인
함수 호출 : 입력에 대한 출력이 반환값으로 존재하면 함수 호출이라고 한다.
프로시저 호출 : 출력에 해당하는 반환값 없이 모듈화해 놓은 서브루틴의 실행을 위한 호출임
함수가 호출되면
1. 현재 fp에 저장된 주소 정보를 스택에 쌓는다.
2. sp의 값을 fp에 저장한다.
3. 함수 호출에 의한 실행의 이동
Pc ( program count) 레지스터
명령어를 순차적으로 fetch하기 위해 Code 영역에서 현재 실행되는 명령어가 있는 주소를 저장하는 레지스터이다. Fetch 연산이 일어날 때마다 자동으로 pc값이 증가한다. Pc 레지스터를 조작하면 절차지향을 거스를 수 있어..
Instruction Regisdter
명령어를 가져오기 위해서 사용되는 레지스터이다. 함수 호출 시 pc값을 저장하는 역할이다(함수종료 시 돌아갈 값을 백업). 덮어 써지는 경우는 stack에 보관한다.
코드 영역 : 프로그램이 동작하기 위한 프로그램 코드가 올라가는 위치이다. Fetch 단계에서 명령어를 가져오는 위치는 프로그램 코드가 존재하는 코드 영역이다. 즉, 이진화된 명령어들이 Fetch 가 이루어지면 RAM의 메모리 영역 중 Code 영역에 올라오는 것이다.
4. 함수 호출 규약
함수 호출 규약(Calling Convention)
함수 호출 시 인자를 전달하는 방식과 스택 프레임을 반환하는 방식을 약속해 놓은 것을 가리켜 함수 호출규약이라 부른다.
전달 인자를 스택에 쌓는 방법이나 스택 프레임을 반환하는 방식이 하나가 아니기 때문에 미리 약속해 놓는 것이다.
CALLBACK함수는 Window 시스템에서 __stdcall을 매크로로 지정한 것이다.
단순히 이게 아닐수도? Callback 함수란 Window 시스템에 의해 자동으로 호출되는 함수이다. 특정 상황에서 호출되어야 할 함수를 등록시키는 것이 가능한데 이때 등록되는 함수를 가리켜 콜백 함수라고 한다.
__cdecl : C/C++ 디폴트 호출 규약
11장 쓰레드의 이해
1. 쓰레드란 무엇인가?
다시 컨텍스트 스위칭
프로세스의 상태 정보를 저장하고 복원하는 일련의 과정이다. 성능 저하의 원인이고.
컨텍스트 스위칭은 멀티 프로세스를 운영하기 위해 필요하다. 근본적으로 본다면 프로세스는 서로 완전히 독립적이기 때문이라고도 볼 수 있다. A 프로세스에는 A프로세스 데이터만 저장되므로 B프로세스를 위해서는 A프로세스가 사용하는 CPU 자리를 완전히 넘겨줘야한다. CPU 뿐만 아니라 메모리 까지 자리를 내줘야한다.(?)
프로그램이 서로 다르다면 프로세스는 서로를 공유할 수 없다. 하지만 하나의 프로그램에서 둘 이상의 실행 흐름을 두기 위해서는 프로세스처럼 모든 것을 독립적으로 둘 필요는 없다. 이렇게 등장한 것이 쓰레드이며 스레드와 프로세스의 가장 큰 차이점이다.
자세하게 생각해보면 레지스터 자체에서는 프로세스를 교체하나 쓰레드를 교체하나 컨텍스트 스위칭에 별 차이는 없다. 그러나 캐시 메모리를 고려해서 생각하면 쓰레드가 훨씬 빠르다는 것을 알 수 있다. 쓰레드가 변경되더라도 캐시에 존재하는 메모리를 교체 없이 사용할 수 있기 때문이다 (스택을 제외한 데이터 영역은 공유되므로). 반면 프로세스가 교체되면 캐시에 저장된 메모리는 사용할 수 없으므로 모두 RAM에서 새로 가져와 교체해줘야한다.
저장하고 복원하는 컨텍스트 정보의 개수를 줄여주는 방법으로 컨텍스트 스위칭에 소요되는 시간을 줄일 수 있다. 컨텍스트 정보는 프로세스의 상태 정보와 관련이 있으므로 프로세스 상태 정보를 줄인다는 말과 동일하다.
프로세스는 완전히 독립된 두 개의 프로그램 실행을 위해서 사용된다.
쓰레드는 하나의 프로그램 내에서 둘 이상의 프로그램 흐름을 만들어 내기 위해 디자인 된 것이다.
쓰레드는 쓰레드간 공유하는 상태정보가 있다. -> 컨텍스트 스위칭을 빠르게 하는 요ㅗ이닝다.
프로세스처럼 완벽히 독립적인 구조가 아닌 쓰레드끼리 공유하는 요소가 있다. 이 요소 덕분에 컨텍스트 스위칭이 프로세스에 비해 빠르다.
프로세ㄴ스는 메모리 구조상 다른 프로세스와 완전히 독립적이다. 각각이 stack heap data code 영역을 가지고 있으며 서로 데이터를 주곧 받기 위해서 IPC가 필요하다.
스레드는 생성하면 해당 스레드만을 위한 stack 영역만 생성하고 그 이외의 영역은 프로세스 영역을 공유한다.
스레드의 특징 : 스레드마다 스택을 독립적으로 할당한다.
스택은 함수 호출 시 필요한 메모리 영역이다. 실행 흐름의 추가를 위한 최소 조건이 독립된 스택이라고 볼 수 있다. 그리고 실행 흐름은 함수 단위로 이루어진다고도 정리하면 되겠고.
스레드의 특성 : 코드 영 역을 공유한다.
코드 영역 : 작성한 코드가 이진화된 명령어로 변환되어 있는 데이터이다.
코드 영역이 공유된다는 것은 프로세스에 있는 명령어(함수 등)를 쓰레드에서도 사용할 수 있다는 것이 된다. 프로세스에 있는 함수를 스레드는 호출할 수 있다.
스레드의 특성 : 데이터 영역과 힙영역을 공유한다.
따라서 IPC 통신기법 없이 전역변수나 동적 메모리 공간을 공유할 수 있다.
Window 시스템에서는 프로세스는 단순히 쓰레드를 담는 상자이다.
스레드가 없는 프로세스는 존재하지 않으며… 프로세스 내에서 기본적으로 생성되는 스레드에 의해 main 함수가 호출된다. 이러한 스레드를 main 스레드라고 한다 ( main 함수를 호출하는 스레드)
2. 쓰레드 구현 모델에 따른 구분
커널레벨 쓰레드 vs 유저레벨 쓰레드
쓰레드 기능을 제공하는 주체가 누군지에 따라 나눠진다.
커널레벨 쓰레드
쓰레드를 생성 및 스케줄링 하는 주체가 커널인 경우, 커널레벨 쓰레드라고한다.
커널레벨에서 쓰레드가 지원된다는 뜻이다.
스케줄러와 스레드 정보는 커널영역에 존재한다. 따라서 운영체제는 쓰레드의를 확인할 수 있다.
스케줄러는 쓰레드를 대상으로 스케줄링한다.
유저레벨 쓰레드
커널에 의존적이지 않은 형태로 쓰레드의 기능을 제공하는 라이브러리를 활용할 수 있는데 이러한 방식으로 제공되는 쓰레드가 유저레벨 쓰레드이다.
유저영역에서 실행된다.
스케줄러가 스케줄링하는 대상은 프로세스이다(쓰레드가 아니다)
커널 영역에는 쓰레드에 대한 정보가 존재하지 않으므로 운영체제는 쓰레드의 존재를 알 수 없고 확인도 불가능하다.
커널영역 : 운영체제라는 하나의 소프트웨어를 실행시키기 위해서 필요한 메모리 공간이다.
유저영역 커널영역 외 메모리 공간, 즉 운영체제가 아닌 프로그램을 실행시키기 위 해서 필요한 메모리 공간이다.
커널영역과 유저영역을 분리한 이유 : 안전성을 위해서이다. 운영체제에서 오류가 생긴다면 컴퓨터 전체에 문제가 생긴다. 따라서 유저가 직접 커널에 접근할 수 없도록 영역을 아예 분리시킨 것이다.
스케줄러가 동작하려면 커널 모드로 전환되어야 한다.
유저모드에서는 커널영역에 접근이 불가능하다.
커널모드에서는 eahems 영역의 접근이 허용된다.
모드 전환은 시스템에 붖담을 준다.
유저모드와 커널모드를 제공하는 것은 프로세서이다. (메모리 보호기능은 CPU에게 있다)
커널레벌 쓰레드
장점
커널에서 직접 제공해주기 때문에 안전성과 다양한 기능성이 제공된다.
단점
커널에서 제공해주는 기능이므로 유저모드에서 커널모드로의 전환이 빈번하게 일어난다. 따라서 이는 성능의 저하로 이어지게 된다.
유저 레벨 쓰레의 장점 및 단점
장점 ; 커널은 쓰레드의 존재조차 모른다. 오로지 유저 모드로 동작하기 때문에 유저 모드에서 ㅋ ㅓ널 모드로의 전환이 필요 없다. 때문에 성능이 좋다.
단점 ; 운영체제는 프로세스의 존재만 알고 쓰레도의 존재를 모른다. 따라서 결과를 예측하기 어렵게 된다. (쓰레드 이후 여러 쓰레드가 동작하는 구조에서 첫번째 쓰레드가 정지되면 운영체제는 나머지 쓰레드의 존재를 모르므로 나머지 쓰레드도 동작할 수 없게된다. )
13장 쓰레드 동기화 기법1
1. 쓰레드 동기화란 무엇인가?
스레드 동기화 : 쓰레드의 실행순서를 정의하고 이 순서대로 실행되도록 하는 것이다. 또한 메모리 접근에 있어서 동시접근을 막는 것 또한 쓰레드의 동기화에 해당한다.
유저모드 동기화 : 동기화를 유저 영역에서 진행하는 기법이다. 커널 모드로 전환하지 않으므로 성능상 이점이 있으나, 기능의 제한도 존재한다.
컬너모드 동기화 : 동기화를 커널 영역에서 진행하는 기법이다. 커널 모드로 전환해야하므로 성능은 떨어지지만 커널 영역에서 제공하는 기능을 제공받을 수 잇다.
2. 임계 영역 (Critical Section)접근 동기화
원래 임계 영역이란 둘 이상의 쓰레드가 동시에 실행될 경우 생길 수 있는 동시 접근 문제를 발생시킬 수 있는 코드 블록을 임계 영역이라고 한다.
임계영역이란 배타적 접근(한 순간에 하나의 쓰레드만 접근)이 요구되는 공ㅇ유리소스에 접근하는 코드 블록이다.
임계 영역에 대한 해결책은 임계 영역의 동시접근을 막는 것이다.
*앞으로 살펴볼 크리티컬, 인터락, 뮤텍스, 세마포어 동기화 기법들은 단순히 임계 여영ㄱ 접근을 제한하기 위한 동기화 방법이다(메모리 접근에 대한 동기화라고도 할 수 있다.) 쓸데ㅡ의 실행 순서를 동기화하는 기법은 14장에서 알아볼 것이다.
3 유저모드 동기화
크리티컬 섹션 기반의 동기화 (코드블록 자체를 의미하는 임계영역과 동음이의어)
크리티컬 섹션 오브젝트를 만들고 초기화 한다.
임계영역이 시작되기 전에 크리티컬 오브젝트 섹션을 획득하고 임계영역이 끝나면 크리티컬 섹션 오브젝트를 반환하는 원리이다. 이러한 크리티컬 섹션 오브젝트를 통해 한 순간에 하나의 쓰레드만 실행될 수 있게 되는 것이다.
인터락 함수 (Interlocked Family of Function) 기반의 동기화
함수 내부적으로 한 순간에 하나의 쓰레드에 의해서만 실행되도록 동히화되어있다.
Volatile 키워드 : 최적화를 수행하지 않고, 메모리에 직접 연산하는 키워드이다.
외부요인으로 인해 변수의 값이 언제든지 변할 수 있는 경우 volatile 키워드를 사용한다.
컴파일러는 이 변수에 대해서 최적화를 수행하지 않는다. 또한 변수를 참조하는 경우 레지스터에 로드된 값을 사용하지 않고 매번 메모리를 참조한다.
왜? 멀티 쓰레드 환경에서는 서로 공유되는 전역변수에 대한 값은 언제든지 변할 수 있기 때문이다.
4 커널모드 동기화
뮤텍스 기반 동기화
뮤텍스는 뮤텍스 오브젝트를 생성하는 쓰레드에게 기회를 먼저 줄 수 있다.
생성되는 뮤텍스는 커널 오븢게터 : 커널 레벨 동기화 기법
초기화 함수의 호출이 필요 없다 ( 크리티컬 섹션 동기화 기법과의 차이점)
생성함수 과정에 서 필요한 초기화가 모두 이루어지기 때문이다.
임계영역에 진입하기 앞서 ㅁㅠ텍스를 획득한다. 뮤텍스가 획득 가능한 상태라면 커널 오브젝트는 signaled 상태이다. 뮤텍스를 획득하게되면 해당 커널 오브젝트 상태는 Non_Sinaled 상태로 변경되어 다른 쓰레드들은 임계영역에 진입할 수 없게된다.
커널 오브젝트의 상태를 이용하여 임계영역 진입점을 구분짓는다. (커널 오브젝트 상태는 쓰레드가 실행중인지 종료중인지를 확인할 수 있다)
세마포어(Semaphore) 기반의 동기화
커널모드동기화이며 뮤텍스와 비슷하다고 할 수 있다.
차이점은 카운트라는 개념이 존재한다는 점이다. 해당 임계 영역에 접근 가능한 숫자를 미리 설정해둔 후 세마포어 동기화가 실행될때마다 카운트를 줄인다. 카운트가 0이되면 해당 임계영역에 더 이상의 쓰레드는 접근할 수 없게된다. 즉, 설정해놓은 수만큼의 쓰레드가 접근할 수 있는 동기화 기법이다.
이름있는 뮤텍스를 사용하는 이유는… 윈도우가 관리하고 있는 커널 오브젝트에 접근 가능한 핸들 정보를 얻기 위해서이다.
음.. 뮤텍스는 커널 오브젝트이므로 특정 프로세스 영역에 존재하는 것이 아니야. 커널이 관리하는 오브젝트이므로 해당 뮤텍스를 생성하지 않은 다른 프로세스에서도 접근이 가능하다.
다만 핸들의 유효성이 문제이다. :>>>> 핸들과 핸들 테이블의 소유 및 유효성에 대한 내용확인
핸들 테이블은 커널 오브젝트와 이를 지칭하는 핸들값에대한정보를 담고있는 테이블이다. 프로세스별로 독립적이다. 따라서 특정 프로세스는 다른 프로세스에서 생성된 뮤텍스에 접근이 불가능하다. 다른 프로세스를 통해 만들어진 커널 오브젝트인 관계로 핸들 테이블에 대한 정보가 없기 때문이다. >>> 이거 잘 이해가 안된다. 프로세스간 통신으로 해결할 수 없는 문제인가? 그리고 애초에 핸들 테이블에 대한 개념을 까먹음…
이러한 문제 때문에 뮤텍스에 이름을 붙여주는 것이다. 이 이름은 Windows 운영체제 내에서 유일한 이름이다. 이 이름을 통해 Windows 가 관리하고 있느 커널 오브젝트에 접근 가능한 핸들 정보를 얻을 수 있다.
뮤텍스의 소유와 WAIT_ABANDONED
세마포어는 세마포어를 획득한 쓸데ㅡ와 반환하는 쓸레드가 달라도 문제없다.
그러나 뮤텍스는 그렇지 않다 ( 이거도 잘 이해가… 세마포어도 같아야하지 않나?)
14장 쓰레드 동기화 기법2
1. 실행순서에 있어서의 동기화
스레드 동기화 : 쓰레드의 실행순서를 정의하고 이 순서대로 실행되도록 하는 것이다. 또한 메모리 접근에 있어서 동시접근을 막는 것 또한 쓰레드의 동기화에 해당한다. 추가로 이야기하자면 메모리 접근에 대한 동기화(임계 영역 접근에 대한 동기화) 역시 쓰레드의 실행 순서 동기화에 포함되는 개념이다. 다만 포커스가 어떠한 것인지를 부각하기 위해서 나눴을 뿐이다.
생산자 소비자 모델
하나의 쓰레드가 입력과 출력을 모두 관리한다면… 출력속도보다 빠르게 입력되면 제대로 출력되지않는 문제가 발생하게 된다.
이러한 문제를 해결하기 위해 입력 출력 쓰레드를 따로 분리하고, 그 사이에 메모리 버퍼를 둔다.
이처럼 쓰레드의 실행 순서를 동기화하는 일을 생산자 소비자 모델이라고 할 수 있다.
이벤트 기반 동기화
세마포어, 뮤텍스와 같이 이 기법역시 동기화를 위한 오브젝트를 사용한다. 명칭은 ‘이베늩 오브젝트’이다. 보편적으로 ‘이벤트’라고만 부르기도 한다.
이벤트 오브젝트 활용방법
쓰레드나 프로세스의 커널 오브젝트는 초기에 non_signaed, 종료되는 경우 자동으로 signaled 상태로 변경된다.
그러나 이벤트 오브젝트는 종료할 때 직접 sinaled 상태로 변경해줘야한다.
직접 함수 호출을 통해 이벤트 오브젝트의 상태를 sinaled 상태로 변경해야한다.
이벤트 커널 오브젝트는 ㄹ프로그래머의 요청에 의해 Signaled 상태가 된다.
자동리셋 모드 오브젝트라면 non_signaled 상태로의 변화가 자동으로 이루어짐
수동리셋모드 이벤트는… 원하는 타이밍에 둘 이상의 스레드를 동시에 깨워서 실행해야할 때 아주 좋음. 하지만 둘 이상의 스레드 순서는 텍스를 함께 사용해야 해결가능하다.
잘이해못했어 인터네 ㅅ 찾아보자.
2. 이벤트 더하기 뮤텍스
ㅇ