정글 27일차

윤종성·2024년 7월 27일
0

c언어

목록 보기
2/4

오늘 배운 것들

1. C언어 - 가상메모리

프로그램이 실행될 때 실제 메모리 주소 대신 가상 주소를 사용하게 하는 기술
운영체제게 실제 메모리 주소를 대신 관리한다.
메모리 공간이 작았던 시절 중요하게 여겨졌던 개념
현재에도 여러 장점들로 가상 메모리를 사용하고 있다.

1-1. 특징

  1. 주소 공간 분리
    각 프로그램은 독립된 가상 주소 공간을 가지며, 서로 간섭할 우려 없이 실행할 수 있다.
    프로그램이 혼자 메모리 공간 전체를 점유한 것처럼 사용할 수 있다.
  2. 메모리 확장
    실제 메모리보다 더 큰 (논리)메모리 공간을 사용할 수 있다.
  3. 스와핑
    사용하지 않는 메모리 페이지를 디스크로 옮겨 실제 메모리 공간을 확보할 수 있다.

1-2. 구성

(x86-64에서의 예시)
(C언어 예시)

  1. 코드(텍스트) 영역:
    • 기계어 코드가 저장
    • 읽기 전용
  2. 데이터 영역:
    • 초기화된 전역 변수와 정적 변수가 저장
  3. BSS 영역:
    • 초기화되지 않은 전역 변수와 정적 변수가 저장
    • 프로그램 시작 시 0으로 초기화됨
  4. 힙 영역:
    • 동적 메모리 할당 시 사용
    • 런타임 중 크기가 확장될 수 있음
  5. 스택 영역:
    • 함수 호출 시 스택 프레임으로 영역이 확장되고, 함수 종료 시 해제됨
    • 스택 프레임에는 레지스터 저장 값, 지역 변수, 함수 인자, 리턴 주소를 저장
      3번까지는 컴파일 단계에서 크기가 결정된다.

1-3. 저장수명

C언어에서는 저장수명이라는 개념을 통해 개체가 메모리에 존재하는 기간을 구분한다.

  1. automatic
    블록이 실행될 때 할당되고, 블록이 끝나면 해제.
    일반적으로 스택에 저장(지역변수)
  2. static
    프로그램의 시작부터 끝까지 존재
    데이터 영역이나 BSS 영역에 저장(전역변수, 정적변수)
  3. allocated
    메모리 할당 함수(malloc, calloc, realloc)를 통해 할당하고 해제(free)
    힙 영역에 저장(동적 메모리 할당)

1-4. 동적 메모리 할당

프로그램 실행 중(런타임) 필요에 따라 메모리를 할당하고 해제하는 것
stdlib.h헤더를 통해 사용할 수 있다.

  1. malloc
    지정된 크기(바이트)의 메모리를 할당하며, 성공 시 할당된 메모리의 포인터를 반환

    int *ptr = (int *)malloc(sizeof(int) * 10); // 10개의 int 크기만큼 메모리를 할당
  2. calloc
    지정된 크기와 숫자를 곱한 크기의 메모리를 할당하며, 성공 시 할당된 메모리의 포인터를 반환
    malloc과 다르게 0으로 초기화 된다. 구조체 배열 등 일괄 초기화가 필요할 때 유용하다.

    int *ptr = (int *)calloc(10, sizeof(int)); // 10개의 int 크기만큼 할당하고 0으로 초기화
  3. realloc
    동적으로 할당된 메모리 블록의 크기를 확장하거나 축소하며, 성공 시 할당된 메모리의 포인터를 반환.
    실패 시 NULL포인터를 반환하며 기존 메모리 블록은 변경되지 않는다. 따라서 예외 처리를 하지 않을 경우 기존의 주소를 잃어버릴 수 있다.
    확장 시 해당 주소 앞 뒤로 여유가 충분하지 않으면 다른 메모리로 주소를 이전하고 데이터를 복제한다. 따라서 포인터를 재할당하여 사용해야 한다.

    ptr = (int *)realloc(ptr, sizeof(int) * 20); // 메모리 블록 크기를 20개의 int크기로 확장
  4. free
    동적으로 할당된 메모리를 해제

    free(ptr); // 할당된 메모리를 해제

2. 가상화

가상화(假像化, virtualization)는 컴퓨터에서 컴퓨터 리소스의 추상화를 일컫는 광범위한 용어이다.
이것은 *다중 논리 리소스로서의 기능을 하는 것처럼 보이는* 서버운영 체제, 응용 프로그램, 또는 저장 장치와 같은 하나의 단일 물리 리소스를 만들어 낸다.
아니면 *단일 논리 리소스처럼 보이는* 저장 장치나 서버와 같은 여러 개의 물리적 리소스를 만들어 낼 수 있다.
/wikipedia

여러 자원을 하나의 자원인 것처럼 사용하거나, 하나의 자원을 여러 자원인 것처럼 사용(조금 더 흔한 경우)하는 것.
실제로 존재하는 자원의 형태를 감추는 추상화의 일종이라고 볼 수 있다.

  1. 플랫폼(컴퓨터) 전체를 시뮬레이트하는 경우를 플랫폼 가상화(하드웨어 가상화),
  2. 저장장치, 응용프로그램 등 일부 리소스를 시뮬레이트하는 경우를 리소스 가상화라고 한다.

2-1. 공통 요소

GPT에 요구해서 공통 요소를 추려냈으나 흔하게 언급하는 개념은 아닌 것 같다.

  1. 자원 추상화 (Resource Abstraction)
    • 설명:
      가상화는 물리적 자원을 추상화하여 가상 자원으로 변환
      즉, 물리적 자원을 가상화된 형태로 감추어서, 물리적 자원의 세부사항에 구애받지 않고 접근하고 사용
    • 목적:
      사용자나 응용 프로그램이 자원을 더 쉽게 관리하고 활용
  2. 격리 (Isolation)
    • 설명:
      가상화는 서로 다른 가상 환경이나 가상 자원이 서로 독립적으로 작동하도록 보장
      하나의 환경에서 발생한 문제나 변화가 다른 환경에 영향을 미치지 않음
    • 목적:
      자원의 효율적인 활용과 보안을 강화
      다수의 가상 환경이 동일한 물리적 자원을 공유하더라도 서로 간섭하지 않도록 함

2-2. 종류

광범위한 개념인 만큼 가상화 대상에 따라
1. 하드웨어 가상화
2. 운영체제 가상화
3. 애플리케이션 가상화
4. 네트워크 가상화
5. 스토리지 가상화
6. 데스크톱 가상화
7. 메모리 가상화
8. 디스크 가상화
등 다양한 가상화 기술이 존재한다.

2-2-1. 하드웨어 가상화

하이퍼바이저(소프트웨어)로 많이 구현된다.
cpu, 메모리를 포함한 모든 컴퓨터를 가상화해 별도의 독립된 컴퓨터를 실행하는 것처럼 보이게 한다(가상 머신, VM).
클라우드 컴퓨팅, 서버 가상화 등으로 활용된다.

2-2-2. 컨테이너 가상화

하드웨어 자체를 가상화해 운영체제를 구동하는 방식은 무겁고 느리다는 단점이 있다.
반면 컨테이너는 하이퍼바이저를 통해 독립된 운영체제를 실행하는 것이 아니라 운영체제 커널을 공유하며 프로그램의 실행 환경만 독립적으로 만든다.
이는 프로그램이 독립된 운영체제에서 돌아가는 것 처럼 만들어 준다.

3. 연습문제

3-1. 스택과 큐 4번

void reverse(Queue *q)
{
    ListNode *cur, *cur_s;
    Stack s;
    s.ll.head = NULL;

    while (q->ll.head != NULL) {
        cur = q->ll.head;
        q->ll.head = q->ll.head -> next;
        cur->next = s.ll.head;
        s.ll.head = cur;
    }

    if (s.ll.head != NULL) {
        cur_s = s.ll.head;
        s.ll.head = s.ll.head->next;
        q->ll.head = cur_s;
        cur = q->ll.head;
    }
    while (s.ll.head != NULL) {
        cur_s = s.ll.head;
        s.ll.head = s.ll.head->next;
        cur->next = cur_s;
        cur = cur->next;
    }
}

처음에는 연습문제 파일 내부의 push, pop, enqueue, dequeue를 이용해보려 하였으나 마지막 노드의 next를 널 포인터로 초기화를 안 해주어서 오류가 났다.
그냥 직접 짰다.
포인터는 꼭 초기화를 해주고 쓰자.

profile
알을 깬 개발자

0개의 댓글