inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

[인프런 워밍업 클럽 3기 - CS] 2주차 발자국

한선규
0

학습 내용 회고: 이번 2주차는 운영체제를 공부하며 정말 재미를 느꼈습니다. 평소에 윈도우 설정을 보면서 그냥 넘어갔던 용어들 ex.조각 모음 같은 용어의 뜻을 알게 되어 너무 재밌게 수강했습니다.

 

 

1강 프로세스 간 통신

프로세스 간 통신(Inter-Process Communication, IPC)은 같은 컴퓨터 안에서 프로세스들끼리 데이터를 주고받거나, 네트워크로 연결된 다른 컴퓨터의 프로세스와 데이터를 주고받는 기술이다.

한 컴퓨터 내에서의 통신 방법

  1. 파일(File): 여러 프로세스가 하나의 파일을 읽고 쓰면서 데이터를 공유하는 방식.

  2. 파이프(Pipe): 운영체제가 제공하는 파이프를 통해 데이터를 주고받는 방식.

  3. 쓰레드(Thread): 같은 프로세스 내에서 공유하는 CODE, DATA, HEAP 영역 중 DATA와 HEAP을 이용해 통신하는 방식.

네트워크를 이용한 통신 방법

  1. 소켓(Socket) 통신: 네트워크를 통해 데이터를 주고받는 방식.

  2. 원격 프로시저 호출(RPC, Remote Procedure Call): 네트워크를 통해 다른 컴퓨터의 함수를 호출하는 방식.


2강 공유자원과 임계구역

프로세스 간 통신을 할 때 여러 프로세스가 공동으로 사용하는 변수나 파일을 공유자원(Shared Resource)이라고 한다.

문제점: 동기화(Synchronization) 문제

→ 이를 해결하려면 임계구역(Critical Section) 개념이 필요하다.

공유자원 사용 시 발생하는 문제

임계구역 문제 해결을 위한 상호 배제(Mutual Exclusion) 메커니즘

  1. 임계구역에는 동시에 하나의 프로세스만 접근 가능해야 한다.

  2. 여러 프로세스가 접근을 요청해도 한 번에 하나만 들어갈 수 있어야 한다.

  3. 임계구역에 들어간 프로세스는 최대한 빨리 나와야 한다.


3강 세마포어(Semaphore)

세마포어는 상호 배제(Mutual Exclusion) 메커니즘 중 하나로, 공유자원에 대한 접근을 조절하는 역할을 한다.

세마포어 개념

세마포어는 프로세스가 공유자원에 접근하기 전에 획득하고, 사용이 끝나면 해제하는 방식으로 동작한다.


4강 모니터(Monitor)

세마포어의 단점을 보완한 상호 배제 메커니즘으로, 운영체제가 아닌 프로그래밍 언어 차원에서 지원하는 동기화 기법이다.

모니터의 특징

예시

image.png

위 코드에서 프로세스 A가 increase() 메서드를 실행 중이면, 프로세스 B는 decrease()를 실행할 수 없다.

결론 모니터는 세마포어보다 더 직관적이고 안전한 동기화 메커니즘을 제공하여, 동기화 코드를 쉽게 작성할 수 있도록 해준다.

 

데드락(교착상태)

여러 프로세스가 서로 다른 프로세스의 작업이 끝나길 기다리다 아무도 작업을 진행하지 못하는 상황을 교착상태라 한다.

ex. 프로세스A: 프로세스B가 자원을 줘야 실행 됨

 프로세스B: 프로세스C가 자원을 주길 기다리고 있음.

 프로세스C: 프로세스 A가 자원 주면 지원해주겠음. 

교착상태의 발생 원인은 공유자원 때문이다.

교착상태의 필요조건 4가지(모두 충족해야함)

  1. 상호배제(어떤 프로세스가 리소스를 점유했다면 그 리소스는 다른 프로세스에게 공유 되면 안된다.)

  2. 비선점(프로세스 A가 리소스를 점유하고 있는데 프로세스 B가 리소스를 빼앗을 수 없어야함.)

  3. 점유와 대기(어떤 프로세스가 리소스 A를 점유하고 있는 상태에서 리소스 B를 원하는 상태)(오른쪽 포크를 쥔 상태에서 왼쪽 포크를 원하는 상태)

  4. 원형 대기(점유와 대기를 하는 프로세스들의 관계가 원형을 이루고 있어야한다.)

(1번은 자원이 공유될 수 있는지, 2번은 점유된 리소스를 빼앗을 수 있는지)

교착상태를 예방하는 방법은 너무 비효율적이었다.

그래서 교착상태에 빠졌을 때 해결방법을 알아보겠다.

교착상태 회피(Deadlock avoidance)

운영체제가 프로세스들에게 자원을 할당할 때 어느정도 자원을 할당해야 교착상태에 이르는지 파악하고 발생하지 않는 수준의 자원을 할당한다.

교착상태 회피는 할당된 자원의 수를 기준으로 안정 상태와 불안정 상태로 나뉜다.

운영체제는 최대한 안정 상태를 유지하려고 자원할당을 한다.

불안정상태여도 교착상태에 무조건 빠지는 것이 아닌 확률이 높아지는 것.

(은행원 알고리즘)

운영체제는 프로세스들에게 자원을 할당하기 전에 자원을 얼마나 가지고 있는지 즉 총 자원을 알고있다.

프로세스들은 자기가 필요한 자원의 최대 숫자를 운영체제에게 알려줘야함. 이를 최대 요구 자원 이라 함.

안정상태

시스템의 총 자원=14 사용가능한 자원=2

프로세스 최대 요구 자원 현재 할당된 자원 요청이 예상되는 자원 P1 9 5 4 P2 6 4 2 P3 4 3 1

이 상황에서 P1이 4개를 요구하면 요구를 취소하고 P2에게 빌려줌.

그 후 P2가 작업을 마치고 6개를 반납함 so P1, P3 요구 전부 가능.

불안정상태

시스템의 총 자원=14 사용가능한 자원=1

프로세스 최대 요구 자원 현재 할당된 자원 요청이 예상되는 자원 P1 9 7 2 P2 6 4 2 P3 4 2 2

P1, P2, P3 의 요청 전부 불가능함.

지금처럼 불안정상태라해도 모든 프로세스가 최대 요구 자원을 요구하지 않는 이상 교착상태에 빠지진 않지만 요구한다면 교착상태에 빠진다.

이는 비효율적이다.

교착상태를 어떻게 검출해낼까?

  1. 가벼운 교착 상태 검출(프로세스가 일정시간 작업을 진행하지 않는다면 교착상태가 발생했다 간주& 해결)(해결: 일정 시점마다 체크포인트를 만들어 작업을 저장하고 타임아웃으로 교착상태가 발생했다면 마지막으로 저장했던 체크포인트로 롤백하는 것)

  2. 무거운 교착 상태 검출(자원할당 그래프를 이용함, 현재 운영체제에서 프로세스가 어떤 자원을 사용하는지 지켜보고 교착상태가 발생했다면 해결한다. 그래프를 보고 HOW? ,그래프를 보고 순환 구조를 파악한 뒤 교착상태를 발생시킨 프로세스를 강제 종료 시킴. 다시 실행시킬 때 체크포인트로 롤백시킴)(이는 주기적으로 자원할당 그래프를 검사해야 하기 때문에 오버헤드가 발생함)(하지만 가벼운 교착 상태 검출로 검출 될 수 있는 억울하게 종료되는 프로세스는 발생하지 않는다.)

컴파일과 프로세스

1. 프로그래밍 언어: 컴파일 언어 vs 인터프리터 언어

프로그래밍 언어는 컴파일 언어인터프리터 언어로 구분할 수 있다.

컴파일 언어

인터프리터 언어

2. 프로세스의 메모리 구조

프로세스는 실행될 때 CODE, DATA, HEAP, STACK 영역으로 나뉜다.

① 코드(Code) 영역

② 데이터(Data) 영역

③ 스택(Stack) 영역

④ 힙(Heap) 영역

3. 컴파일 언어의 실행 과정

컴파일 언어로 작성된 코드가 실행 파일이 되기까지의 과정은 다음과 같다.

#include <stdio.h>
#define MY_NUMBER 100

int main() {
    int num1 = 50;
    printf("result: %d", num1 + MY_NUMBER);
    getchar();
    return 0;
}

실행 과정

  1. 전처리기 (Preprocessor)test.i

    • #include <stdio.h>의 내용을 포함시키고, #define MY_NUMBER 100을 치환한다.

    • 코드에 있는 모든 주석을 제거한다.

  2. 컴파일러 (Compiler)test.s

    • C 코드(test.i)를 어셈블리 코드로 변환한다.

  3. 어셈블러 (Assembler)test.o

    • 어셈블리 코드를 목적 파일(기계어)로 변환한다.

  4. 링커 (Linker)test.exe

    • 여러 목적 파일과 라이브러리를 합쳐 실행 파일(Executable)을 생성한다.

실행 파일과 프로세스

이러한 과정을 통해 프로세스가 실행되며, CPU가 이를 스케줄링하여 프로그램이 동작하게 된다.

 

메모리의 종류와 주소 체계

1. 메모리의 종류

컴퓨터에서 사용되는 주요 메모리는 다음과 같이 구분된다.

1.1 레지스터 (Register)

1.2 캐시 메모리 (Cache Memory)

1.3 메인메모리 (RAM, Random Access Memory)

1.4 보조 저장장치 (HDD, SSD)


2. 메모리와 주소 체계

운영체제는 메모리를 효과적으로 관리하기 위해 1바이트 단위로 구역을 나누고 각 구역에 **주소(Address)**를 부여한다.

2.1 32비트 vs 64비트 CPU

2.2 물리 주소와 논리 주소

2.3 절대 주소 vs 상대 주소

2.4 메모리 주소 변환 예시

  1. 사용자가 논리 주소 0x100의 데이터를 요청

  2. CPU가 메모리 관리자에게 0x100번지 데이터를 요청

  3. 메모리 관리자는 **재배치 레지스터 값(예: 0x4000)**을 더해 **절대 주소 0x4100*의 데이터를 가져옴

  4. 프로그램 시작 주소가 변경되더라도 재배치 레지스터 값만 수정하면 됨

메모리 할당 방식

과거 유니프로그래밍 환경에서는 메모리보다 큰 프로그램을 실행할 때 필요한 부분만 메모리에 올리고, 나머지는 하드디스크에 저장하는 메모리 오버레이 기법을 사용했다. 이를 통해 큰 프로그램을 여러 조각으로 나누어 일부만 실행하며, 나머지는 하드디스크의 스왑 영역에 저장했다.

현대의 멀티프로그래밍 환경에서는 메모리 할당 방식이 **가변 분할 방식(세그멘테이션)**과 **고정 분할 방식(페이징)**으로 나뉜다.


1. 가변 분할 방식 (세그멘테이션)

장점

단점


2. 고정 분할 방식 (페이징)

장점

단점


메모리 단편화 문제와 해결 방법

외부 단편화

내부 단편화


버디 시스템

예시

  1. 2048B(2^11)의 메모리가 있음

  2. 500B 크기의 프로세스 A가 메모리를 요청

  3. 512B(2^9) 크기의 블록을 할당

이처럼 프로세스 크기에 맞게 할당되며, 불필요한 공간 낭비를 줄일 수 있음.


현대의 메모리 관리 방식

현재는 가변 분할(세그멘테이션)과 고정 분할(페이징) 방식을 조합하여 사용한다.

이를 통해 내부·외부 단편화 문제를 최소화하면서도 효율적인 메모리 활용이 가능하다.

답변 0