메모리 계층(Memory hierarchy)과 가상 주소 공간(VAS)

얕은 복사(shallow copy) vs 깊은 복사(deep copy)

  • 리스트 예시

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    li = [1, 2, 3]

    # 참조(reference). 둘은 완벽하게 같은 객체.
    li2 = li
    li2
    >> [1, 2, 3]

    li2.append(4)
    li
    >> [1, 2, 3, 4]
  1. 얕은 복사(shallow copy)

    • 얕은 복사를 하면 공간을 복사해서 다른 공간이 생긴다.

    • 하지만 바라보고 있는 대상이 리스트 안에 리스트일 경우는 다르다.

      • 이름 객체가 같은 곳을 바라보고 있기 때문에 기존 대상과 같이 바뀌게 된다.
    • pythontutor.com을 통해 이해하자.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      li3 = li.copy()  # 얕은 복사
      li3
      >> [1, 2, 3, 4]

      li3.append(5)
      li3
      >> [1, 2, 3, 4, 5]

      li
      >> [1, 2, 3, 4]

      # 리스트 안에 리스트를 넣을 경우
      li = [1, 2, 3, 4, [6, 7]]

      li3 = li.copy() # 얕은 복사
      li3
      >> [1, 2, 3, 4, [6, 7]]

      # 리스트 안에 리스트에 요소 값 추가
      li3[4].append(8)
      li3
      >> [1, 2, 3, 4, [6, 7, 8]]

      # 원래 있던 리스트 안 리스트도 바뀜
      li
      >> [1, 2, 3, 4, [6, 7, 8]]
  2. 깊은 복사(deep copy)

    • 깊은 복사를 하면 완전히 다른 객체를 만들어버린다.

    • 기존 대상이 복사한 대상과 같지 않다.

    • pythontutor.com을 통해 이해하자.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      import copy

      li4 = copy.deepcopy(li) # 깊은 복사
      li4
      >> [1, 2, 3, 4, [6, 7, 8]]

      li4[4][1] = 10
      li4
      >> [1, 2, 3, 4, [6, 10, 8]]

      li
      >> [1, 2, 3, 4, [6, 7, 8]]

Computer Engineering

  • Instruction Cycle(명령 주기)

    1. fetch

      • PC(Program Counter)가 가리키고 있던 Instruction을 Memory로부터 가져옴
    2. decode

      • CU(Control Unit)이 IR(Instruction Register)에 있는 값을 가지고 분석 및 해석
    3. execute

      • 실제로 동작(실행)
  • Memory Layout(Segment)

    • 메모리 영역은 크게 다음과 같이 나뉜다.(stability)
    1. 프로그래머들이 코딩할 수 있는 User 영역

    2. OS 관련 코드가 있는 Kernel 영역

    • User 영역에서 함부로 Kernel 영역에 접근할 수 없다.(security)

      • window 98에서는 Kernel 영역의 메모리를 바꿀 수 있어서 위험했다.(블루 스크린)
    • User 영역은 다음과 같다.

    1. code segment

      • Instruction이 된 코드가 저장됨
    2. data segment

      • 전역 변수 저장

      • 초기값이 있으면 data 영역에 할당

      • 초기값이 없으면 BSS 영역에 할당

      • 프로세스가 시작될 때 생성되고, 프로세스가 종료될 때 소멸됨

    3. heap segment

      • 프로그래머가 원할 때 지정할 수 있는 영역

      • 프로그래머가 원할 때 생성하고 소멸할 수 있음

    4. stack segment

      • 지역 변수 저장

      • 함수가 호출될 때 생성되고, 함수가 종료될 때 소멸됨

      • stack 크기는 기본적으로 1MB가 잡혀있다.

      • heap은 크기가 제한되어 있지 않아서 stack 공간을 만날 때까지 계속 커질 수 있다.

  • Heap

    • 단점

      1. 메모리 누수(memory leak)

      2. 느리다.(malloc이 느리다.)

      3. 메모리 단편화(memory fragmentation)

      • 2번과 3번이 연관됨
    • Stack과 Heap 비교

    1. Stack

      • stack pointer가 top을 가리키고 있기 때문에 할당할 지점을 찾을 필요가 없다.

      • 그래서 stack은 빠르다.

    2. Heap

      • 메모리에 비어있는 공간을 찾아야 한다.

      • memory header는 몇바이트가 저장되는지 기억하고 있다.

      • 전체 메모리 상에서는 충분하나, 조각조각으로 나뉘어져 있는 부분을 더한 것이기 때문에 단편화가 일어난다.

        1
        2
        3
        8byte의 메모리 공간이 필요한 시점에서...
        4byte, 4byte, 2byte의 메모리들을 더하면 10byte로 충분해보인다.
        하지만 나누어져 있는 메모리이기 때문에 사용이 불가하다.
      • Default Heap

        • 프로세스가 생성될 때 제일 먼저 잡히는 heap 공간
      • Dynamic heap

        • 내가 원하는 만큼 heap의 크기를 받아서 조절해서 프로그램하는 것

        • dynamic heap으로 구현한 것 중 하나가 python이다.

        • dynamic heap을 통해 memory 단편화를 해결할 수 있다.

      • Garbage collection

        • 언어 차원에서 메모리를 관리해주는 것(heap을 관리해줌)

        • reference counter 값이 0이 된 메모리를 지워준다.

          • import sys의 sys.getrefcount() 함수 사용 가능

          • 카운트 값은 실제 카운트 값보다 1이 큰 값

        • C++도 shared counter 기법을 통해 메모리 누수 문제를 해결할 수 있다.

  • 가상 주소 공간(VAS. Virtual Address Space)

    • OS가 프로세스가 시작될 때 할당해주는 가상 메모리 공간

    • Virtual Memory = RAM + Page file

    • OS가 프로세스를 시작하면 4GB를 할당해준다.

    • 즉, 프로세스가 페이지 테이블을 Main Memory에 만들고 페이지 테이블의 첫 주소를 가르쳐준다.

    1. Logical address(논리 주소)

      • VAS에 있는 메모리 주소
    2. Physical address(물리 주소)

      • Main memory에 있는 메모리 주소
    • 0x00000000 ~ 0xFFFFFFFF 중에서 앞에 0x”00000”까지가 주소를 가리킨다.

    • 나머지 뒤에 0x”000”이 Offset(해당 페이지 시작으로부터 주소까지 거리)이다.

    • 즉, 논리 주소(LA)를 물리 주소(PA)로 바꾸려면 앞 5자리만 바꾸면 된다.

    • Page Table

      • VAS에서의 논리 주소(LA)와 물리 주소(PA)가 기록된다.

      • 두 주소가 모두 올라와 있으면 1로, 아니면 0으로 판단하는 유효 비트(valid bit)도 존재 한다.

    • MMU(Memory Management Unit)

      • PC가 가리키고 있는 논리 주소(LA)를 물리 주소(PA)로 바꿔준다.

      • run-time mapping

    • Preparing

      • 프로그램을 실행하면 page table이 만들어진다.

      • page table에서 지금 당장 필요할 것 같은 코드를 HDD에서 main memory로 가져오는 것을 말한다.

    • Page Fault

      • CPU가 logical memory를 요구하면 MMU가 physical memory로 바꿔서 가져온다.

      • page table에 physical memory가 없고, vaild bit가 0인 상황이다.

      • 이렇게 되면 HDD에서 원하는 데이터를 main memory에 올린다.

      • 그 후, page table의 physical address를 가져오고 valid bit가 1이 되서 다시 동작하게 된다.

      • 제일 처음에 메모리를 가져올 때에는 page fault가 무조건 일어나게 된다.

      • 메모리를 가져올 때까지는 아무런 동작을 할 수 없다.

    • Thrashing

      • CPU 프로그램 처리 시간보다 page 교체에 더 많은 시간을 보내는 것을 말한다.

      • main memory의 page 부재가 비정상적으로 많이 발생하여 CPU가 프로그램 처리보다 페이지 교체에 더 많은 시간을 보내 성능이 급격히 줄어드는 현상이다.

      • 멀티 프로세싱 기능을 갖춘 시스템에서 가상 메모리의 페이지 부재(page fault)가 너무 많이 발생하여 프로세스 실행보다 페이지 교체에 더 많은 시간을 소모하는 현상이다.

Share