리눅스 프로세스의 메모리 구조

세그먼트

세그먼트는 적재되는 데이터의 종류별로 메모리의 구역을 나눈 것으로 용도에 따라 5가지로 구분한다.

  • 코드 세그먼트
  • 데이터 세그먼트
  • BSS 세그먼트
  • 스택 세그먼트
  • 힙 세그먼트

 

Segment

 

메모리의 구역을 나누면 운영체제가 용도에 따라 적절한 접근권한을 설정할 수 있다는 장점이 있다.

접근권한에는 읽기, 쓰기, 실행이 존재하고 CPU는 부여된 권한에 대해서만 행동할 수 있다.

 

ex)

데이터 세그먼트는 프로그램이 실행되면서 사용되는 데이터가 적재된다.

CPU는 해당 메모리에서 값을 읽어와야 하므로 읽기 권한이 주어진다.

대신 이곳의 데이터는 실행 대상이 아니기 때문에 실행 권한이 주어지지 않는다. 

 

 

 

 

 

코드 세그먼트

실행 가능한 기계 코드가 위치하는 영역으로 텍스트 세그먼트(Text Segment)라고도 불린다.

프로그램이 동작하려면 코드가 실행이 되어야 하므로 이 영역엔 읽기실행 권한이 부여된다.

공격자가 악의적인 코드를 삽입할 수 있으므로 쓰기 권한은 부여하지 않는다.

 

 

아래 코드가 컴파일되면 554889e5b8697a00005dc3라는 기계 코드로 변환되는데, 이 기계 코드가 코드 세그먼트에 위치하게 된다.

 

int main() { return 31337; }

 

 

 

 

 

데이터 세그먼트

데이터 세그먼트(Data Segment)에는 컴파일 시점에 값이 정해진 전역 변수 및 전역 상수들이 위치한다.

CPU가 이 세그먼트의 데이터를 읽을 수 있어야 하므로, 읽기 권한이 부여된다.

데이터 세그먼트는 쓰기가 가능한 세그먼트와 불가능한 세그먼트로 다시 나뉜다.

 

쓰기 가능한 세그먼트 - data 세그먼트

프로그램이 실행되면서 값이 변할 수 있는 데이터들이 위치한다.

 

 

쓰기 불가능한 세그먼트 - rodata(read-only data) 세그먼트

상수와 같이 값이 변하면 안 되는 데이터들이 위치한다.

 

 

str_ptr은 "readonly"라는 문자열을 가리키고 있는데, 이 문자열은 상수 문자열로 취급되어 rodata에 위치하며, 이를 가리키는 str_ptr전역 변수로서 data에 위치합니다.

 

int data_num = 31337;                       // data
char data_rwstr[] = "writable_data";        // data
const char data_rostr[] = "readonly_data";  // rodata
char *str_ptr = "readonly";  // str_ptr은 data, 문자열은 rodata
int main() { ... }

 

 

 

 

 

BSS 세그먼트

Block Started By Symbol Segment: 컴파일 시점에 값이 정해지지 않은 전역 변수가 위치하는 메모리 영역

BSS에는 선언만 하고 초기화하지 않은 전역변수 등이 위치한다.

이 세그먼트의 메모리 영역은 프로그램이 시작될 때 모두 0으로 값이 초기화 되며 읽기 권한 및 쓰기 권한이 부여된다.

 

 

아래 코드에서 초기화되지 않은 전역 변수인 bss_data가 BSS 세그먼트에 위치하게 된다.

 

int bss_data;
int main() {
  printf("%d\n", bss_data);  // 0
  return 0;
}

 

 

 

 

 

스택 세그먼트

프로세스의 스택이 위치하는 영역으로 함수의 인자나 지역 변수 등이 프로그램 실행중이 저장되는 곳이다. 

스택 세그먼트는 스택 프레임 단위로 사용되며 스택 프레임은 함수가 호출될 때 생성되고, 반환될 때 해제된다.

 

사용자의 입력에 따라 프로그램의 실행 흐름이 크게 바뀌기 때문에 스택 프레임의 크기를 미리 예측할 수 없다.

따라서 운영체제는 작은 크기의 스택 프레임을 할당해주고 부족하면 더 확장하는 식으로 운영하고 있다.

→ 스택에 대해서 이를 "아래로 자란다"라고 표현함.

 

이 영역에는 CPU가 자유롭게 값을 읽고 쓸 수 있어야 하기 때문에 읽기와 쓰기 권한이 부여된다.

 

 

아래의 코드에서는 지역변수 choice가 스택에 저장된다.

 

void func() {
  int choice = 0;
  scanf("%d", &choice);
  if (choice)
    call_true();
  else
    call_false();
  return 0;
}

 

 

 

 

 

힙 세그먼트

힙 데이터가 위치하는 세그먼트로 동적으로 할당되는 데이터가 여기 저장된다.

C언어에서 malloc(), calloc() 등을 호출해서 동적 할당 받는 경우 등이 해당된다.

해당 영역은 읽기쓰기 권한이 부여된다.

리눅스에서는 스택 세그먼트와 반대 방향으로 자란다.

 

 

아래 예제 코드는 heap_data_ptr에 malloc()으로 동적 할당한 영역의 주소를 대입하고, 이 영역에 값을 쓴다.

heap_data_ptr지역변수이므로 스택에 위치하며, malloc으로 할당받은 힙 세그먼트의 주소를 가리킵니다.

 

int main() {
  int *heap_data_ptr =
      malloc(sizeof(*heap_data_ptr));  // 동적 할당한 힙 영역의 주소를 가리킴
  *heap_data_ptr = 31337;              // 힙 영역에 값을 씀
  printf("%d\n", *heap_data_ptr);  // 힙 영역의 값을 사용함
  return 0;
}

 

 

 

 

 


Quiz

퀴즈 1

 

퀴즈 2

 

퀴즈 3

 

퀴즈 4

 

퀴즈 5

 

퀴즈 6

 

퀴즈 7

 

:)

복사했습니다!