프로그램
- 어떤 작업을 위해 실행할 수 있는 파일
프로세스
- 프로그램을 실행해 운영체제로부터 시스템 자원(CPU와 RAM)을 할당받는 작업의 단위, 프로그램의 인스턴스
- 프로세스가 유저모드에서 실행되면 커널이 메모리를 할당해줌 -> 이때 실제 메모리가 아니라 가상 메모리(RAM + HDD)를 할당해줌
- 각각 독립된 메모리 영역(code, data, stack, heap)을 할당 받음
- 한 프로세스는 다른 프로세스의 변수나 자료 구조에 접근 불가능, IPC를 사용해야함
- 운영체제는 프로세스를 PCB(Process Control Block)라는 곳에 필요한 정보를 넣어두고 관리함
스레드
- 프로세스가 할당받은 자원을 이용하는 실행의 단위 -> 스레드는 해당 자원으로 제한됨
- 스레드마다 stack(통상적으로 1MB) , 레지스터 등을 할당받고 나머지는 공유
- 각자 Thread Local Storage라는 공간을 가짐
- 프로세스와 같이 TCB가 존재
멀티 프로세스와 스레드
- 멀티 프로세스(멀티 태스킹) : 여러 프로그램을 동시에 사용
- 멀티 스레드 : 하나의 프로그램을 여러 개의 스레드로 구성해 각 스레드가 하나의 작업을 처리, 스레드끼리는 데이터를 공유하기 때문에 효율적인 처리가 가능, 하나의 프로그램안에서 동시에 여러 작업을 수행하기 위해서 사용
- 여러 프로세스나 스레드가 동시에 자원에 접근할 때 더 많은 자원을 확보하기 위한 경쟁조건(Race Condition)이 생김
- 여기서 동시성 및 동기화이 중요하고 이를 위해 시분할사용이라는 개념이 등장
※ 윈도우는 멀티 스레드 중심, 리눅스는 멀티 프로세스 중심
가상 메모리
- Code : 기계어 코드
- Data : 전역 및 정적 변수
- Stack : 지역 변수
- Heap : 동적 할당 변수(malloc)
PCB(Process Control Block)
- PID : Process의 ID(32bit 정수)
- 프로세스의 상태
- 기계어 코드의 주소 등이 포함됨
프로세스 상태
- 생성 상태 : 막 생성된 상태
- 준비 상태 : 입출력을 완료하고 연산할 준비(디스패치 : 준비 상태 -> 실행 상태)
- 실행 상태 : 연산하는 단계(+PCB)
- 완료 상태 : 실행이 끝난 상태(-PCB)
- 대기 상태 : 실행 상태에서 입출 력을 위해 대기하는 상태
- 보류 상태 : sleep(자발적) 대기열에서 이탈하고 재진입하기 때문에 플러스 알파의 시간이 추가적으로 소요됨
- 휴식 상태 : suspend(외부요인) 대기열에서 이탈하고 재진입하기 때문에 플러스 알파의 시간이 추가적으로 소요됨
문맥 교환(Context Switching)
- 하나의 코어가 다수의 프로세스를 처리할 때, 하나의 프로세스가 일정 시간 처리되고 PCB에 상태를 저장한 후 다음 프로세스로 넘어감. 이때 흐름이 일시정지 되고 다시 이어서 실행될 때 문맥이 교환된다고 함
프로세스의 생성과 복사
- 생성 -> 메모리 복사(실행 코드 복사 등) -> PCB 생성 (복잡한 과정)
- Win32 API : CreateProcess(), ExitProcess(), WaitForSingleObject()
- UNIX : fork(), exec(), exit(), wait()
fork는 자식 프로세스를 생성할 때 새로운 프로세스를 생성하는 것과 같이 메모리를 새로 할당
exec는 새로운 메모리를 할당하지 않고, 부모 프로세스의 메모에 자신을 덮어씌움
https://learn.microsoft.com/ko-kr/sysinternals/downloads/process-explorer
#include <iostream>
#include <Windows.h>
#include <process.h>
int g_data;
boolean g_bFlag = true;
HANDLE g_hThreadExit01, g_hThreadExit02, g_hThreadExit03;
void threadFunction01(void* pArg)
{
std::cout << "threadFunction01 - Start\n";
while (g_bFlag) {
g_data = 1000;
}
std::cout << "threadFunction01 - End\n";
::SetEvent(g_hThreadExit01);
}
void threadFunction02(void* pArg)
{
std::cout << "threadFunction02 - Start\n";
while (g_bFlag) {
g_data = 2000;
}
std::cout << "threadFunction02 - End\n";
::SetEvent(g_hThreadExit02);
}
void threadFunction03(void* pArg)
{
for (int i = 0; i < 10; i++) {
std::cout << "threadFunction03() g_data: " << g_data << std::endl;
Sleep(0); //우선순위에서 물러나서 뒤로 빠짐 -> 하기 전과 후에 영향을 미침
}
::SetEvent(g_hThreadExit03);
}
int main()
{
std::cout << "Hello World - Start\n";
g_bFlag = true;
g_hThreadExit01 = ::CreateEventA(nullptr, TRUE, FALSE, "T_THREAD_01");
g_hThreadExit02 = ::CreateEventA(nullptr, TRUE, FALSE, "T_THREAD_02");
g_hThreadExit03 = ::CreateEventA(nullptr, TRUE, FALSE, "T_THREAD_03");
::_beginthread(threadFunction01, 0, nullptr);
::_beginthread(threadFunction02, 0, nullptr);
::Sleep(10);
::_beginthread(threadFunction03, 0, nullptr);
//호출자 스레드 대기상태 전환
//::Sleep(100); //우연에 맡기는 코드
::WaitForSingleObject(g_hThreadExit03, INFINITE);
g_bFlag = false;
//T1, T2의 종료 이벤트를 대기
::WaitForSingleObject(g_hThreadExit01, INFINITE);
::WaitForSingleObject(g_hThreadExit02, INFINITE);
::CloseHandle(g_hThreadExit01);
::CloseHandle(g_hThreadExit02);
::CloseHandle(g_hThreadExit03);
std::cout << "Hello World - End\n";
}
'💻 Computer Science > OS' 카테고리의 다른 글
[OS] 교착상태 (0) | 2023.12.18 |
---|---|
[OS] IPC (0) | 2023.12.18 |
[OS] 스케줄링 (0) | 2023.12.18 |
[OS] 운영체제 (0) | 2023.12.15 |
[OS] 컴퓨터 구성 (0) | 2023.12.15 |