본문 바로가기

CS study/운영체제 - JSCODE 스터디

[2주차 스터디 노트] 프로세스, 프로세스의 메모리 구조, 문맥 교환

 

프로그램과 프로세스

프로그램은 저장장치에 존재하는 컴파일된 코드의 집합이다. 

이것이 실행되기 전까지는 그저 저장장치에 존재되는 데이터에 불과하지만, OS에서 명령을 받아 메모리에 적재하게 되면 그때부터는 운영체제의 관리를 받으며 CPU 자원을 통해 동작하는 '프로세스' 가 된다.

 

프로세스는 CPU 자원을 사용하고 운영체제의 관리를 받으며, 프로그램 코드를 실제로 실행하는 동적인 개체

 

프로그램이 메모리에 적재되는 순간 프로세스가 된다.

 

<백그라운드 프로세스>

이중 눈에 보이지 않는 백그라운드 프로세스를 유닉스 체계의 운영체제에서는 데몬(daemon)이라고 부르고, 윈도우 운영 체제에서는 서비스라고 부른다.

 

프로그램은 어떤 과정을 거쳐 메모리에 적재되는가?

프로그램이 메모리에 적재되는 일반적인 과정

 

1. 프로그램 실행 요청: 특정 프로그램을 실행하라는 명령을 운영체제에 전달

2. 파일 시스템 접근: 운영체제는 파일 시스템을 통해 해당 프로그램의 실행 파일(예: .exe, .bin 등)을 검색

3. 실행 파일 분석: 운영체제는 실행 파일의 헤더를 읽어 파일 형식을 확인하고, 필요한 메모리 크기와 종류를 결정한다. 실행 파일에는 프로그램 코드와 데이터, 초기화에 필요한 정보 등이 포함되어 있다.

4. 메모리 할당: 운영체제는 프로그램이 필요로 하는 메모리를 할당한다. 프로그램의 코드, 데이터, 스택, 힙 영역 등에 대한 메모리 공간을 포함할 수 있다. (프로세스 메모리 할당)

5. 실행 파일 로드: 프로그램의 실행 파일에서 필요한 부분(코드와 초기화 데이터)을 메모리로 복사

6. 재배치와 링킹: 프로그램이 동적 링크 라이브러리(DLLs)나 다른 외부 리소스를 참조하는 경우, 해당 주소를 실제 메모리 주소로 매핑한다. 재배치 과정을 통해 프로그램의 코드와 데이터가 올바른 메모리 위치를 참조하도록 조정된다.

7. 시작 주소 설정: 프로그램의 진입점(예: main 함수)에 해당하는 메모리 주소를 설정한다.

8. 프로세스 생성: 운영체제는 프로세스 제어 블록(PCB)을 생성하여 프로그램의 상태, 프로그램 카운터, 레지스터 상태 등의 정보를 관리한다.

9. 실행 제어 전달: 운영체제는 CPU에 프로그램을 실행하라는 명령을 전달하고, 프로그램 카운터는 프로그램의 시작 주소로 설정됩니다. 이 때부터 프로그램은 프로세스로서 실행을 시작한다.

 

프로세스

프로세스의 메모리 구조

 

실행되고 있는 프로세스는 메모리 공간을 시스템으로부터 할당받는다.

이러한 메모리 공간은 RAM 등에 적재되어 필요할 경우 CPU에서 메모리를 읽어 작업을 수행하게 된다.

메모리 공간은 크게 코드/데이터/스택/힙 영역으로 나뉜다.

메모리 구조 도식도 :&nbsp;https://velog.io/@matcha_/%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B5%AC%EC%A1%B0%EB%A5%BC-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90

1. Code

- 실행할 프로그램의 코드를 저장 (기계어로 이루어진 명령어가 저장)

- CPU는 이 코드 영역에서 명령어를 가져와 처리하게 된다.

- 코드 영역에는 데이터가 아닌 CPU가 실행할 명령어가 담겨 있기 때문에 쓰기가 금지되어 있다.

 

2. Data 

- 정적 할당 영역

- 전역변수와 정적 변수를 저장. (프로그램이 실행되는 동안 유지할 데이터가 저장)

- BSS(Block Stated Symbol) 영역에는 초기화되지 않은 전역변수나 Static 변수를 저장

BSS는 메모리 할당의 효율성을 높이는 것에 중점을 둔다.

프로그램 시작 시 초기화되지 않은 전역 변수와 정적(static) 변수를 저장

프로그램이 실행될 때 이 영역에 있는 모든 데이터는 기본적으로 0으로 설정 (메모리 절약)

 

실제로 값이 할당되기 전에는 이 변수들을 디스크에 저장할 필요가 없기 때문에, 공간이 절약된다.
즉, 실행 파일에 이 변수들에 대한 실제 데이터를 저장하지 않는다.
대신 실행 시에 메모리에 할당하고 기본값으로 설정(null, 0)한다.

 

3. Stack

- 동적 영역. 데이터를 일시적으로 저장하는 영역

- 지역변수나 매개변수, 리턴 값 등 임시로 사용하는 데이터를 저장하는 영역

- 변수 생성 시 할당되고, 반환 시 소멸(함수 리턴 등으로)

- 커널 영역을 보호하기 위해 메모리의 높은 주소에서 낮은 주소의 방향으로 메모리가 할당된다.

(위에서 아래로 좁혀 들어온다.)

- 이 영역은 LIFO(Last In First Out) 방식으로 작동 (함수 구조와 지역 변수 처리에 있어서 매우 효율적이기 때문)

- 흔히 발생하는 스택오버플로우가 해당 스택 메모리가 넘쳐서 발생하는 에러.

 

  • Stack Overflow : 스택이 힙 영역을 침범
  • Heap Overflow : 힙이 스택 영역을 침범

4. Heap

- 동적 데이터 영역 : 프로그래머가 필요할 때마다 사용하는 메모리 영역으로 메모리 공간이 동적으로 할당되고 해제된다.

- 스택과 유사하지만 반대로 동작 : 커널 영역을 보호하기 위해 메모리의 낮은 주소에서 높은 주소의 방향으로 메모리가 할당

- 힙 영역을 제대로 반환하지 않는다면 메모리 누수 발생

 

5. 공유 메모리

- 다수의 프로세스들이 데이터를 공유하기 위해 사용하며, 이 영역을 통해 다른 프로세스들은 메모리를 효율적으로 공유하며 통신할 수 있다.

- 일반적으로 IPC(Inter-Process Communication)의 한 형태로 사용

 

1. 프로세스가 Kernel에 공유 메모리 생성 요청

2. Kernel은 User 영역에 공유 메모리 공간을 할당하고, 공유 메모리의 주소를 프로세스 내의 공유 메모리와 매핑
이는 프로세스는 자기 자신의 메모리만 볼 수 있기 때문이다. 매핑 정보를 통해 프로세스가 공유 메모리 영역에 접근할 수 있다.

 

 

 

 

프로세스 제어 블록 : PCB

< PCB란? >

프로세스의 종합적인 정보를 담고 있는 데이터 모음.

CPU는 이런 PCB 블록을 확인하고 프로세스의 정보를 불러들이고, 저장하여 작업을 실행한다.

 

운영체제는 PCB를 통해 프로세스 정보를 확인할 수 있다.

 

주로 적혀있는 내용은 다음과 같다.

 

- PID : 프로세스를 식별하기 위한 고유 번호

- 레지스터값 : 프로세스가 이전까지 실행했던 레지스터의 고유값을 복원한다. (Program Counter 등) 

- 프로세스 상태 : 현재 프로세스의 상태 정보를 저장

- CPU 스케줄링 정보 : 언제, 어떤 순서로 할당받을지에 대한 정보를 기록

- 메모리 관리 정보 : 프로세스가 어디에 저장되었는지를 확인할 수 있는 정보, 페이지 테이블 정

- 프로세스 에 할당된 입출력장치의 정보 

 

< PCB의 존재 이유 >

CPU의 한정된 자원을 할당받기 위해 프로세스는 일정 주기로 순환한다.

 

PCB 블록은 운영체제의 커널 영역에 저장되며, 프로세스와 관련된 정보를 저장한다.

이는 프로세스의 생명주기상 CPU가 컨텍스트 스위칭되며 중간중간 PCB의 정보를 참고하여 프로세스 정보를 불러오기 때문이다.

 

- PCB는 프로세스 생성 시 만들어지고, 프로세스 종료 시 폐기된다.

 

< 프로세스 테이블과 PCB 관리 방식 >

 

운영체제는 빠르게 PCB에 접근하기 위해 프로세스 테이블을 생성하여 PCB를 관리한다.

 

운영체제는 빠르게 PCB 에 접근하기 위해서 프로세스 테이블을 사용해 각 프로세스의 PCB 를 관리한다.

각각의 PCB는 연결 리스트 방식으로 관리된다. 이는 프로세스가 생성과 삭제 과정에서 중간 PCB의 삽입 삭제가 용이하기 때문이다.

 

문맥 교환 : Context Switching

 

CPU가 프로세스를 실행시키기 위해 필요한 정보(프로세스 수행을 재개하기 위해 기억해야 할 정보)를 Context(프로세스 데이터, CPU 레지스터 값 등)라고 한다.

이러한 정보들을 교환하는 과정이 Context Switching이다. 이는 CPU가 일정 시간마다 프로세스를 변경하여 여러 프로세스를 동시에 실행하기 때문에 발생한다.

 

- 각 프로세스의 문맥(Context)은 PCB에 저장되어 있다.

- CPU 할당 시간이 완료되거나, 인터럽트가 발생할 경우 프로세스는 상태를 저장하고 PCB에 문맥을 저장한다.

- CPU는 프로세스를 실행할 때, 저장된 문맥 정보를 가져와서 복구한다.

 

문맥 교환의 도식도

 

이처럼 기존 프로세스의 문맥을 PCB에 백업하고, 새로운 프로세스를 실행하기 위해 문맥을 복구하여 새로운 프로세스를 실행하는 것을 문맥 교환(context switching)이라 한다.

문맥 교환의 일련 과정

 

문맥 교환이 너무 자주 발생한다면 오버헤드가 발생하므로 그렇게 좋은 일은 아니다.

또한 교환 과정에서 PCB에 값을 저장하고, 불러들이는 과정이 필요하니 유휴(준비) 상태가 존재하게 된다.

 

문맥 교환이 발생하는 대표적인 경우

- 인터럽트 발생

- CPU 스케줄링에 따른 프로세스 변경

- 시스템 호출(System Call)

- 멀티 스레드 간 문맥 교환(스레드 스케줄링)

- 블로킹 I/O 요청(대기)

- 동기화 메커니즘 대기

 

문맥 교환 과정

  1. 중단(Save): 인터럽트 혹은 트랩에 의한 요청 발생 이후
    현재 CPU를 사용하고 있는 프로세스의 상태(문맥)를 저장한다.
    이 상태에는 프로그램 카운터, 레지스터들의 값, 메모리의 상태 등이 포함된다.

  2. 스케줄링(Schedule):
    운영 체제의 스케줄러가 다음에 실행할 프로세스를 결정한다.
    스케줄링 기법에 따라 달라지며, 프로세스의 우선순위, 실행 대기 시간, 자원 요구 사항 등을 고려하여 이루어진다.

  3. 재개(Restore):
    다음 실행할 프로세스의 문맥(이전에 저장된 상태)을 CPU에 로드한다. 
    정보가 적재된 프로세스는 마지막으로 중단된 지점부터 작업을 재개할 수 있다.

 

예상 질문 리스트

 

  • 프로그램에 대해 설명해주세요.
  • 프로세스에 대해 설명해주세요.
  • 프로세스의 메모리 공간에대해 설명해주세요.
  • 프로세스 제어블록(PCB)에 대해 설명해주세요.
    • PCB에는 어떤 정보가 담겨있을까요?
  • 문맥교환(context switch)에 대해 설명해주세요.
    • 문맥교환은 언제 발생하나요?
    • 문맥 교환 발생 과정에 대해서 조금 더 상세히 설명해주세요.

 

참고 자료

- 혼자 공부하는 컴퓨터 구조 + 운영체제

 

<프로그램과 프로세스>

 

프로세스 메모리 구조

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://shuu.tistory.com/80#head4

 

https://velog.io/@matcha_/%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B5%AC%EC%A1%B0%EB%A5%BC-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90

 

PCB와 문맥 교환

https://velog.io/@nnnyeong/OS-Context-Switching-PCB-Process-Control-Block#pcb-process-control-block

https://yoongrammer.tistory.com/52


문맥 교환 과정

https://j-su2.tistory.com/63

https://aeroej.tistory.com/137

 

.