본문 바로가기

High Level Technique/Window System

메모리 관리 메모리 관리 Virtual Memory Control Reserve는 예약, Commit은 할당, Free는 할당되지 않음을 말한다. Windows 시스템에서 부여할 수 있도록 정의한 페이지의 상태를 말하는 것이다. 페이지의 총 개수는 가상 메모리 크기 / 페이지 하나당 크기 = 페이지의 개수 로 나타낼 수 있다. Commit은 물리 메모리에 할당이 이루어진 부분들이다. malloc을 통해 메모리 할당하는 것 또한 메모리의 페이지는 Commit 상태가 된다. 반대로 할당되지 않은 부분은 free 상태이다. Commit과 Free를 이용해서 상태를 나타낼 수 있지만 Reserve 상태라는 것을 두고 예약 공간을 만들어 둔다. 메모리의 사용량이 늘어남에 따라서 Commit 상태의 페이지 수를 늘릴 수 있는 .. 더보기
비동기 I/O (Asynchronous I/O) 비동기 I/O (Asynchronous I/O) 만들어 놓은 프로그램이 CPU 사용량을 확인했을데 들쭉날쭉하다면 뭔가 잘못만들어 졌을 가능성이 매우 큽니다.사용량이 큰 폭으로 사용된다면 성능저하가 일어나기 때문입니다. 가령 모든 데이터를 받아낸 뒤에 실행이 된다면 데이터를 받아오는 동안에는 어떠한 작업도 하지 못하게 됩니다. 예를 들어 동영상을 볼 때 동영상 데이터를 모두 받아온 뒤 영상이 나온다면 그 동안은 영상을 볼 수가 없게 되는 것이죠. 이러한 방식은 동기 I/O (Synchronous I/O)라 합니다. ANSI 표준 함수를 이용해 만들어진 프로그램들은 Synchronous I/O 방식으로 만들어 집니다. 한번 호출되면 완료될 때까지 유지되는 현상을 Blocking이라 하는데 이러한 함수들을 가.. 더보기
SEH (Structured Exception Handling) SEH (Structured Exception Handling) __try, __except를 이용하는 방법을 말합니다. try에서 실제 처리할 코드를 넣어주고 except에서 예외가 발생했을 때 처리하는 코드를 넣어줍니다. 보통 코드를 작성을하면 if문을 통해서 NULL일 경우에 대해 GetLastError()을 이용하여 어떤 에러가 발생했는지 화인합니다. 모든 부분에 if문을 통해서 처리를 할 수도 있지만 SEH를 이용할 수도 있습니다. Termination Handler Termination Handler는 종료 핸들러라고 하는데 이 핸들러에서 사용되는 키워드는 __try, __finally를 사용합니다. 123456789101112131415161718192021222324252627#includ.. 더보기
캐쉬와 가상메모리 캐쉬와 가상메모리 12345678910111213141516171819202122232425262728293031323334#include #define ARR_LEN 5 void bubblesort(int srcArr[], int n){ int i, j, temp; for(i = 0; i RAM > 하드 디스크 순으로 갈 수록 더 큰 블록을 가져오게 됩니다. L1 캐쉬가 가득찬 상태에서 데이터가 없어 L2 캐쉬에서 가져오게 될 경우에는 캐쉬 교체 정책에 의하여 가장 오래전에 참조된 블럭을 밀어 내 버립니다. 가상 메모리 메인 메모리는 1GB인데 어덯게 프로세스에 4GB를 할당해서 사용할 까요? 가령 16M의 메모리를 사용하는 환경이 있다고 한다면 물리 메모리 관점으로만 보자면 정확히 16MB의 메모리 .. 더보기
쓰레드 풀 (Thread Pool) 쓰레드 풀 (Thread Pool) 쓰레드가 계속해서 생성되고 소멸되면 시스템에 많은 부담을 줍니다. 쓰레드를 소멸시키지 않고 다시 사용하는 것을 쓰레드 풀이라고 합니다. 123456789101112131415161718192021typedef void(*WORK) (void); typedef struct __WorkerThread{ HANDLE hTread; DWORD idThread; } WorkerThread; struct __ThreadPool{ WORK workList[WORK_MAX]; WorkerThread workerThreadList[THREAD_MAX]; HANDLE workerEventList[THREAD_MAX]; DWORD idxOfCurrentWork; DWORD idxOfLas.. 더보기
생산자/소비자 모델 생산자/소비자 모델 생산자/소비자 모델을 풀어 말하면 실행 순서에 있어서의 동기화라고 할 수 있다. 가령 빵을 만드는 생산자가 빵을 구워서 테이블에 두면 소비자는 빵을 사먹을 수 있다. 이 순서가 바뀌어 소비자가 비어있는 테이블에 빵을 찾게 되고 그 뒤 생산자가 빵을 놓게 된다면 적절하지 못한 순서가 된 것이다. 실행 순서가 동기화 되지 못한것이다. 실행 순서에 있어서 동기화를 생산자/소비자 모델이라 부르는 이유이다. 이를 바탕으로 한 쓰레드가 문자를 입력 받고 출력하는 역할을 모두 실행한다면 출력속도가 입력속도를 따라가지 못하는 경우가 발생하게 되고 어느 순간 문자열이 손실될 것입니다. 위와 같은 현상을 방지하고자 두개의 쓰레드를 이용합니다. A 쓰레드는 입력만 받고 B 쓰레드는 출력만 하는 것이죠.A.. 더보기
쓰레드 동기화 쓰레드 동기화 동기화라는 단어는 무언가 상태가 동일함을 말하는데 쓰레드 동기화는 정해진 순서가 잘 지켜지고 있음을 말합니다.A 쓰레드의 결과를 B쓰레드가 출력을 한다고 가정할때 정상적인 순서로는 A 쓰레드가 실행이 된 후 B 쓰레드가 실행이 되어야 합니다. 하지만 B 쓰레드가 먼저 실행되면 정상적으로 출력할 수 없게 되죠. 따라서 쓰레드의 실행 순서를 정의하고 이 순서에 맞게 따르도록 하는 것이 쓰레드 동기화 라고 합니다. A 쓰레드와 B 쓰레드가 같은 메모리 영역에(데이터, 힙)에 접근한다면 문제가 발생할 것입니다. 이러한 동시 접근을 막는것 도한 동기화에 해당합니다. 동기화의 두가지 방법 유저모드 동기화동기화가 진행되면서 커널의 힘을 빌리지 않는 기법을 말합니다. 커널 모드로 전환이 불필요하기 때문에.. 더보기
Thread 생성과 소멸 Thread 생성과 소멸 Windows에서 쓰레드를 생성하는 함수는 CreateThread()이다. 쓰레드의 최대 개수는 메모리가 허용하는 만큼 가능하다. 쓰레드 또한 독립된 스택을 사용하기 때문에 이러한 스택을 만들기 위해 메모리가 허용하는 만큼가능하다. CountThread.cpp1234567891011121314151617181920212223242526272829303132333435363738394041424344#include #include #include #define MAX_THREAD (1024*10) DWORD WINAPI ThreadProc(LPVOID lpParam){ DWORD threadNum = (DWORD)lpParam; while (1) { printf("Thread nu.. 더보기
쓰레드 (Thread) 쓰레드 (Thread) 하나의 프로그램이 둘 이상의 프로세스를 생성한다면 컨텍스트 스위칭이 비번하게 일어납니다. 앞서 포스팅에서 컨텍스트 스위칭이 빈번하게 일어나면 성능저하가 일어난다고 했습니다.그렇다면 컨텍스트 스위칭이 적게 일어나면 되는데, 풀어 말하면 저장하고 복원하는 컨텍스트의 정보 개수를 줄이면 됩니다. 프로세스의 경우 완전히 독립적인 영역이기 때문에 공유를 할 수 없지만 쓰레드의 경우에는 하나의 프로그램에서 둘 이상의 흐름을 만들어 내기 위한 것이기 때문에 프로세스와 달리 공유하는 상태 정보가 있습니다. 따라서 쓰레드를 사용하는 이유에는 공유하는 요소가 잇고, 컨텍스트 스위칭에 걸리는 시간을 줄이기 위한 것입니다. 쓰레드의 특성 1. 쓰레드마다 스택을 독립적으로 할당한다. 프로세스와 마찬가지로.. 더보기
우선순위 알고리즘 우선순위 알고리즘 프로세스마다 우선순위를 부여해 우선순위가 높은 프로세스를 먼저 실행시키는 방식이다. 가령 A프로세스가 B프로세스 보다 높은 우선순위를 가진다고 한다면 일반적으로 생각해 봤을 때 A프로세스가 어느정도 실행이되고, B프로세스 또한 어느정도 실행된다고 생각할 수 있다. 하지만 보편적인 운영체제에서 B프로세스는 실행이 되지 않는다. 이 상태를 기아상태라고한다. 그렇다면 반대로 일반적으로 생각하는 것이 맞다면 A와 B프로세스가 단순히 임의의 메시지를 출력하낟고 한다면 I/O 작업을 하는 과정에서 낮은 우선순위르 프로세스가 실행될 수 있다.이와 같은 상태에서 기아상태가 발생하는 것은 매우 드문일이다. 라운드로빈 알고리즘 그렇다면 우선순위가 같은 경우 어떤 프로세스를 먼저 실행시켜야 할까? 프로세스.. 더보기
프로세스 환경변수 프로세스 환경변수 환경변수는 프로세스별로 별도의 메모리 공간에 문자열 데이터를 저장하고 관리 할 수 있도록 되어있습니다. 문자열 구조는 key = value로 이루어져 있습니다.마치 python에서 dictionary 방식? 이라고 생각하면 쉬울 것 같습니다. EnvParent.cpp 123456789101112131415161718192021222324252627#include #include #include int _tmain(int argc, TCHAR* argv[]){ SetEnvironmentVariable(_T("Good"), _T("morning")); SetEnvironmentVariable(_T("Hey"), _T("Ho!")); SetEnvironmentVariable(_T("Big").. 더보기
Anonymouse Pipe, Named Pipe Anonymouse Pipe, Named Pipe Windows에서 파이프는 두가지가 존재하는데 Anonymouse Pipe와 Named Pipe가 있습니다. Anonymouse Pipe는 부모 자식 관계 프로세스(혹은 자식, 자식)들 사이에서 통신하는 경우에 유용합니다. Named Pipe는 주소 정보가 존재하는 파이프인데, 주소가 있다는 것은 서로 관계가 없는 프로세스들 사이에서도 주소 정보를 공유함으로써 데이터를 주고 받을 수 있다는 것입니다. 앞서 메일슬롯과의 차이를 보자면 Named Pipe는 양뱡향 통신이 가능하다는 것이고 MailSlot은 브로드케스트 방식(단방향)의 데이터 전송이 가능합니다. AnonymousePipe AnonymousePipe.cpp 123456789101112131415.. 더보기
Pseudo Handle, Handle Duplicate Pseudo Handle, Handle Duplicate 자신의 핸들을 얻는 함수로는 GetCurrentProcess()가 있습니다. 이 함수를 이용해서 얻은 핸들을 Pseudo Handle이라고 합니다. Pseudo Handle은 핸들 테이블에 등록되지 않은 핸들이며 그저 약속된 상수가 반환됩니다. 그래서 자식 프로세스로 상속되지 않고 CloseHandle()의 인자로 전달 할 필요가 없습니다. 그러면 실제 핸들 테이블에 존재하는 핸들 값을 어떻게 얻을까요? DuplicateHandle()을 이용해서 핸들을 복사해 줍니다. 가령, 부모 프로세스의 핸들 테이블에서 123이라는 핸들을 자식 프로세스 핸들 테이블에 넣고자 할 때 자식 프로세스의 핸들 테이블에서는 123이라는 핸들 값은 아무런 쓸모가 없죠.그.. 더보기
핸들 테이블과 오브젝트 핸들의 상속 핸들 테이블과 오브젝트 핸들의 상속 지금까지 핸들 값을 받아오고 종료하는 것에 대해서 공부했습니다. Mailslot을 만들 때 CreateMailslot()을 통해서 메일 슬롯을 만들었는데 이 메일 슬롯 또한 커널 오브젝트가 존재합니다.앞서 지금까지 설명한 내용을 바탕으로 핸들이라는 것이 해당 커널 오브젝트를 지정하고자 정수 값으로 나타낸 것이라고 했습니다. 그렇다면 생성된 Mailslot의 주소가 0x1000이라고 하고 핸들 값을 123이라고 하면 해당 핸들을 가지고 CloseHandle()을 통해서 소멸시킬 수 있었습니다.그러면 단순히 Handle 값만 알고 어떻게 0x1000에 있는 커널 오브젝트를 찾아가 소멸시킬 수 있었을까요? 이러한 이유는 핸들 테이블이라는 것이 존재하기 때문입니다. 핸들 테이.. 더보기
커널 오브젝트 상태 (Kernel Object State) 커널 오브젝트 상태 (Kernel Object State) Windows 운영체제에 의해 생성되는 커널 오브젝트는 두가지 상태가 존재한다.Signaled, Non-Signaled 이 두가지 인데, 이러한 값은 커널 오브젝트를 구성하는 멤버변수에 FASLE, TRUE를 이용하여 상태를 저장한다. 처음 커널 오브젝트가 생성되면 Non-Signaled 상태가 된다. 그러다 프로세스가 종료되면 Signaled 상태가 된다. 즉, 실행 중일 때는 Non-Signaled가 되고 종료 시에는 Signaled 상태가 되는 것이다.이를 보고 프로세스가 실행 중인지 종료된 것인지 알 수 있는 것이다. 그렇다면 Non-Signaled에서 Signaled 상태로 가는 것은 당연하게 생각할 수 있다. 실행하다 종료가 되는 것이.. 더보기
메일 슬롯 (Mail Slot) 메일 슬롯 (Mail Slot) A 프로세스와 B 프로세스가 직접적으로 데이터를 주고 받지 못합니다.(안정성을 위해서. 애초에 메모리 상에 올라가는 주소 영역이 다름.) 이를 해결하기 위한 것이 Mail Slot인데 데이터를 전달하는 것을 Sender 데이터를 받는 것을 Receiver라고 할 때 Sender가 데이터를 보내 Receiver가 바로 받아 처리한다면 좋지만 각 영역에 접근을 할 수 없기 때문에 Sender는 Mail Slot에 데이터를 보내고 Receiver가 Mail Slot에 있는 데이터를 가져옵니다. Sender와 Receiver를 작성할때 CreateFile, WriteFile를 사용하는데 이는 ANSI 표준이 아니고 Windows에서 제공하는 파일 관련 시스템 함수들입니다.함수 이.. 더보기
커널 오브젝트 (Kernel Object) 커널 오브젝트 (Kernel Object) 개념 프로세스의 상태정보(Ready, Running, Blocked)와 우선순위 정보를 예로 들어보자.이러한 정보들을 운영체제 내에서 저장되는데 이러한 정보가 상태나 우선순위가 바뀜에 따라서 갱신되어야 합니다.스케줄러가 위와 같은 정보를 가지고 관리를 할 수 있습니다. 따라서 윈도우 개발자들은 정보를 저장하기 위해서 프로세스 관리 구조체를 만들게 되었고 이를 커널 오브젝트라고 합니다. 이외의 커널 오브젝트 쓰레드, IPC 등을 생성할 때에도 커널 오브젝트가 생성됩니다. 하지만 모든 것이 동일한 구조체로 생성되는 것은 아닙니다. 종류에 따라 서로 다른 구조체가 생성됩니다. 프로세스 우선순위 변경 프로세스의 우선순위를 변경하는 것은 SetPriorityClass().. 더보기
프로세스 프로세스 개념 가령 test.exe 라는 파일이 있으면 보통 프로그램이라고 부릅니다. 혹은 바이너리라고 부릅니다.해당 프로그램을 해당 프로그램은 메모리에 할당이 되고 바이너리 코드가 올라가게 됩니다.이 순간부터 프로그램은 프로세스라고 불립니다. 프로세스 구성 프로그램이 메모리에 할당이 되는 경우 Data, Stack, Heap, Code 영역에 올라가게 됩니다.Data는 전역변수, static 변수가 할당이 되고, Stack 영역에는 지역변수, 함수 호출시 필요한 파라미터(인자 값), Heap 영역은 동적할당, Code 영역은 명령어들이 올라갑니다. Register SetCPU 내의 레지스터들 또한 실행된 프로그램(프로세스)에 필요한 데이터로 채워지게 됩니다. 즉, 메모리 영역과 레지스터들 또한 프로세스.. 더보기
명령어, 레지스터의 구성 명령어, 레지스터의 구성 컴퓨터를 사용하는데 가장 많이 들어본 이야기가 "컴퓨터는 0, 1로만 이해한다." 입니다. 하지만 사람이 0과 1로 보기에는 무리가 있고, 이것을 쉽게 보기위해서 어셈블리어, C언어 등 다양한 언어들이 나왔습니다. 리버싱을 하게되면 어셈블리어를 보게 되는데, 이 어셈블리어는 0과 1로 이루어진 값을 일대일 대응시켜 만들어진 언어입니다. 이러한 어셈블리어들은 어떻게 만들어졌는지 알아보도록 하겠습니다. 현재 많은 컴퓨터들이 64비트로 실행되고 있습니다. 물론 32비트도 많이 있습니다. 하지만 하드웨어사양도 높아지고 처리해야하는 데이터 양도 많이져서 64비트를 많이 사용하고 있습니다.앞서 어셈블리어는 0과 1로 이루어진 값을 일대일 대응시켜서 만들어졌다고 했는데 이번 포스팅에서는 16.. 더보기
Polymorphic Polymorphic Polymorphic은 다형성이라는 뜻을 가지고 있습니다. 말 그대로 다양한 형태를 가지고 있다는 뜻이죠. PTR이 붙어있어서 포인터라고 생각할 수 있지만 포인터값 기반의 연산을 위해서 정의된 자료형입니다. UINT를 사용해서 컴파일을 하게되면 32비트 자료형이 사용됩니다. 만약 64비트로 사용을 할 때에는 UINT64를 이용해야 합니다. 그렇다면 번거롭게 32비트 64비트에 맞춰 코드를 수정하면 매우 귀찮은 일입니다. 위 소스코드 처럼 64비트일 때와 32비트일 때를 구분해서 처리하도록 하면 됩니다. 하지만 이 또한 코드가 깔끔하지 않습니다. 그래서 사용하는 것이 UINT_PTR 입니다. 더보기
x86 & x64 x86 & x64 과거에는 x86 즉, 32비트 운영체제가 많이 사용되어왔습니다. 하지만 현재 대부분의 데스크톱이나 노트북들이 모두 64비트를 지원하고 그만큼 하드웨어 성능 또한 향상되었습니다. 보통 x86과 x64의 차이가 뭐냐?라는 질문에는 x86에서는 메모리를 4G까지 사용할 수 있다. x64에서는 4G이상 사용할 수 있다. 이정도 입니다. 그저 하드웨어적으로 사양을 높이기 위해서 사용하는 것일까요??? 32비트와 64비트의 가장 큰 차이점은 한번에 처리를 할 수 있는 데이터의 크기입니다. 32비트에서는 2의 32제곱 즉, 4GB까지 사용가능하며 64비트는 2의 64제곱으로 16TB까지 사용이 가능합니다.하지만 하드웨어적으로 64비트를 사용하더라고 메인보드에 따라 사용할 수 있는 메모리가 제한되어 .. 더보기
SBCS, MBCS, WBCS SBCS, MBCS, WBCS 이번에는 SBCS, MBCS, WBCS에 대해서 알아보도록 하겠습니다. SBCS, MBCS, WBCS는 Character Sets라고 불립니다. 간단히 말하자면 약속된 문자의 표현 방법이라고 할 수 있습니다. Single Byte Character Set Single Byte Character Set (이하 SBCS)은 문자를 표현하는데 1바이트만 사용하는 방식을 말합니다. 평소 사용되는 문자가 ASCII 코드가 있는데 ASCII 코드가 대표적인 SBCS에 해당합니다. 단순히 ASCII 코드로만 이루어진 문자를 출력하는 것이므로 예제코드는 올리지 않겠습니다. Multi Byte Character Set Multi Byte Character Set (이하 MBCS)은 다양한 .. 더보기
컴퓨터 구조 컴퓨터 구조 컴퓨터 구조에 대해서 알아보도록 하겠습니다. 기능CPU Control Processing Unit (이하 CPU)는 대부분 알고계시는 것처럼 연산을하고 프로그램을 실행하는 곳을 말합니다.CPU에는 ALU, Contorl Unit, Register Set, Bus InterFace가 존재합니다. Arithmetic Logic Unit Arithmetic Logic Unit(이하 ALU)는 간단히 말하자면 연산을 하는 곳입니다. 산술연산, AND, OR과 같은 논리연산을 합니다. Control Unit Control Unit은 ALU가 연산하기 전에 어떤 연산을 하는지 해독을 하는 부분입니다. 가령 어떤 프로그램이 CPU에 전달되어서 실행이 되어야 한다면 컴퓨터는 0, 1과 같은 2진수로만 이해.. 더보기