본문 바로가기

Computer Science/컴퓨터 구조 (Computer Architecture)17

가상메모리 | (3) 세그멘테이션, 페이징 메모리를 관리하는 기법에는 대표적으로 1) 세그멘테이션, 2) 페이징이 있다. 그리고 이 둘을 혼합한 Segmented Paging이나 Paged Segmentation이라는 개념도 있다. 이 중, Linux를 포함한 현대 시스템에서는 주로 페이징이 쓰인다고 한다. 세그멘테이션(Segmentation) 세그먼테이션은 논리적 메모리 영역을 기반으로 프로세스의 데이터를 나누고, 이러한 세그먼트들을 물리적 메모리에 저장하는 방식이다. 세그멘테이션을 수행하는 주요 단계는 다음과 같다: 논리적 구조 기반 분할: 세그멘테이션은 프로그램의 논리적 구조(예: 코드 세그먼트, 데이터 세그먼트, 스택 세그먼트 등)를 반영하여 메모리를 나눈다. 각 세그먼트는 프로그램의 특정 논리적 단위(함수, 데이터 구조 등)를 포함한다... 2023. 11. 15.
가상메모리 | (2) 가상메모리 개념, 가상 주소공간 가상메모리 정의 가상메모리: 메인 메모리의 추상화. 각 프로세스에 하나의 크고 통합된, private한 가상 주소공간을 제공한다. 도입 배경 초기의 cpu들은 물리 주소 방식을 사용했다. 따라서 프로세스가 메인 메모리에 직접 접근할 수 있었고, 이는 메인 메모리의 용량 한계로 인한 프로그램 확장성 제한, 프로세스 간 메모리 영역 침범, 일관되지 않은 주소 등의 문제로 이어졌다. 일반적으로 한 시스템의 여러 프로세스들은 CPU, 메인 메모리를 공유한다. CPU를 공유하는 부분에 대해서는 일반적으로 순서를 기다리느라 단지 느려질 뿐이고 심각한 오류는 발생하지 않는다. 그러나 프로세스들이 존재하는 메모리가 여유가 없이 지나치게 많은 요구에 의해 오염될 경우, 프로그램의 논리와 무관하게 오류가 난다. 이를 방지.. 2023. 11. 15.
가상메모리 | (1) 개발자 코드가 물리 메모리에 닿는 과정 우리가 사용하는 언어는 대개 인간이 읽고 쓰기 쉽도록 설계된 고급언어이다. 고급언어를 통해 소스파일을 작성하고, 큰 프로그램을 설계한다. 고급언어로 짠 코드는 우리의 언어와 비슷하게 생겼다. 근데 이게 어떻게 0과 1뿐인 메모리를 조작할 수 있는 걸까? (방대한 내용을 공부하면서 큰 그림을 이해해보고자 작성한 글이라, 틀린 내용이 있을 수도 있습니다 !! 혹시 발견하신다면 편하게 댓글로 남겨주세요. 공부에 큰 도움이 될 것 같습니다. 🙇🏻) 개발자의 코드가 물리 메모리까지 닿는 과정 우리가 작성한 소스코드는 전처리를 거친 후에 컴파일러가 이를 어셈블리어 코드로 바꾸고, 어셈블러가 이 코드를 다시 기계어로 바꾼다(C언어 기준). 기계어로 된 소스파일은 최종적으로 링킹을 거친다. 이렇게 되면 개발자가 작성.. 2023. 11. 14.
동적 메모리 할당 | Malloc Lab | (4) 할당기 배치 전략 개선 (next fit) 동적 메모리 할당 | Malloc Lab | (1) Malloc은 어떻게 구현되는가?에서, 동적 할당기의 배치 전략에는 대표적으로 세 가지가 있음을 살펴보았다. first fit: 처음부터 탐색하며, 먼저 발견된 충분한 용량의 가용 블록에 할당 next fit: 이전 탐색 지점부터 탐색하며, 먼저 발견된 충분한 용량의 가용 블록에 할당 (-> 빠른 검색) best fit: 모든 블록을 탐색하여, 요청 메모리에 가장 가까운 가용 블록에 할당 (-> 꼼꼼한 검색) 그리고 동적 메모리 할당 | Malloc Lab | (3) 기초적인 할당기 작동 원리, 구현에서, implicit free list의 블록 포맷을 가지고, first fit의 배치전략을 사용하는 기초적인 할당기를 이해해보았다. malloc-lab.. 2023. 11. 14.
동적 메모리 할당 | Malloc Lab | (3) 기초적인 할당기 작동 원리, 구현 컴퓨터 시스템 책의 9.9장에 설명되어 있는 기초적인 버전의 할당기는 다음과 같은 방식을 채택하고 있다. 블록 포맷: 묵시적 가용 리스트 배치 전략: first-fit 전략 연결 전략 즉시 연결: 블록이 반환될 때마다 인접 블록을 통합 인접 블록의 가용여부 확인: 경계 태그(Footer) 활용 해당 버전의 작동 원리, 코드를 이해해보자. 기초적 할당기: overview 우리가 흔히 보는 가상 메모리 그림에서 힙 공간에 돋보기를 대본다고 생각해보자. 그럼 힙 공간은 메모리 블록들의 배열로 표현할 수 있다. (이 '블록들'은 앞 포스팅에서 얘기한 묵시적 가용 리스트 등의 자료구조이다.) 힙 공간을 처음 생성할 때(init)는 최초의 힙 공간을 할당받고, 정렬 패딩, 프롤로그 헤더와 푸터, 에필로그 헤더를 .. 2023. 11. 12.
동적 메모리 할당 | Malloc Lab | (2) 과제 소개 Malloc Lab 과제 Malloc Lab은 CSAPP의 공식 과제 중의 하나이다. 두 저자가 교수로 재직 중인 카네기 멜론 대학은 물론, 세계 곳곳의 컴공과에서 진행 중인 과제이다. malloc을 통해 메모리를 매니징 하는 것을 넘어서, 명시적 할당기 자체를 구현해봄으로써 이해도를 한층 더 높이자는 것이 주 요지이다. 주요 파일 설명 mm.c 학생이 할당기를 구현하는 파일이다. 학생은 mm.c 파일만 수정할 수 있다. (디버깅을 위한 목적 제외) memlib.c 테스트 환경이 돌아갈 힙 공간을 추상화해놓은 파일이다. 학생들은 과제에서 지정해놓은, 제약된 리소스 하에서 힙을 할당받고 활용해야 한다. 힙 공간을 요청하는 함수들(sbrk() 등)이 포함되어 있다. mdriver.c 테스트를 담당하는 파일이.. 2023. 11. 11.
동적 메모리 할당 | Malloc Lab | (1) Malloc은 어떻게 구현되는가? 명시적 할당기, 묵시적 할당기 메모리 할당기는 명시적 할당기(explicit allocator), 묵시적 할당기(implicit allocator)로 나뉜다. 명시적 할당기는 malloc, free 묵시적 할당기는 가비지 컬렉터 명시적 할당기 (malloc) malloc은 힙으로부터 메모리를 할당받는다. 만일 sbrk를 사용한다면, 커널의 brk 포인터에 incr을 더해서 힙 공간을 늘리거나 줄인다. 힙은 블록들로 구성되어 있고, 블록은 워드 단위로 표시된다. (1 워드 = 4byte, 더블 워드 = 8byte) 예를 들어서 '4 워드 블록을 요청한다, 6 워드 블록을 요청한다.' 이런 식으로 표현한다. malloc을 활용한 프로그래밍을 할 시에 주의 사항이 있다. 메모리 블록을 반환 해주고 난 다음엔 .. 2023. 11. 10.
동적 메모리 할당 | 기본 개념, 메모리 누수, 단편화 1. 동적 메모리 할당(Dynamic Memory Allocation)이란? 프로그램이 실행되는 동안 메모리의 크기가 변할 수 있는 변수나 데이터 구조에 메모리를 할당하는 과정을 동적 메모리 할당이라 한다. 이를 통해 런타임에 필요한 메모리 양을 결정하고, 더 이상 필요하지 않은 메모리를 반환하여 재사용할 수 있게 한다. 동적 할당을 통해 메모리 사용을 최적화하고, 프로그램 유연성을 개선할 수 있다. 우선 개념적인 얘기부터 보고, 그 다음에 실제로 어떻게 구현하는지 살펴보자. 동적 vs 정적 메모리 할당 역사적으로 볼 때, 정적 메모리 할당이 먼저 있었고, 프로그램의 요구사항과 컴퓨팅 환경이 발전함에 따라 동적 메모리 할당이 필요해지고 후행적으로 등장했다고 볼 수 있다. 초기에는 정적 메모리 할당이 더 .. 2023. 11. 4.
CS:APP | Chapter 3 | (2) 프로그램의 기계수준 표현 리틀 엔디안 vs 빅 엔디안 메모리에 데이터를 저장할 때, 바이트 저장 순서에 따라 리틀 엔디안, 빅 엔디안으로 나눌 수 있다. 리틀 엔디안 (Little Endian): 낮은 주소에 최하위 바이트(LSB, Least Significant Bit)부터 저장한다 - 사람이 읽고 이해하기엔 직관적이지 않을 수 있다. - 0x1A2B3C4D라는 4바이트 정수를 저장한다고 하면 아래와 같다. (MSB = 0x1A, LSB = 0x4D) 0x103: 0x1A (MSB) 0x102: 0x2B 0x101: 0x3C 0x100: 0x4D (LSB) - 무조건 낮은 메모리 주소에 최하위 바이트(LSB)가 위치하므로, 메모리 주소를 다루기가 쉽다. 낮은 주소(0x100)에서 시작해서 데이터를 읽으면, 그 값이 바로 LSB.. 2023. 11. 1.
CS:APP | Chapter 3 | (1) 프로그램의 기계수준 표현 오버헤드(overhead) 공부하다 보면 함수의 오버헤드가 발생했다, 메모리 오버헤드가 발생했다 등등 overhead 라는 용어가 자주 등장한다. 여기서 말하는 (컴퓨터과학 관점에서의) overhead는 특정 작업을 수행하기 위해 필요하지만, 실제 유용한 작업에 직접 기여하지는 않는 추가적인 리소스나 시간을 의미한다. 즉 특정 작업을 수행할 때, 그 핵심 동작을 위한 비용은 아니지만 괜히 간접적으로 낭비되는, 따라서 더 최적화할 여지가 있는 비용이라는 거다. GPT한테 물어보니 다음과 같은 예시를 준다. 함수의 오버헤드: 함수 호출 시 발생하는 추가적인 처리입니다. 함수를 호출하면, 인자를 전달하고, 리턴 주소를 저장하고, 필요한 경우 스택 프레임을 설정하는 등의 작업이 필요합니다. 이러한 작업들은 함수.. 2023. 10. 31.
CS:APP | Chapter 1 | 컴퓨터 시스템 overview CSAPP 1장의 각 소단원을 읽으면서 주요 내용과 추가적으로 알아본 정보들을 기록하는 포스팅😎 1장은 컴퓨터 시스템 전반을 얕고 넓게 훑는 챕터이다. 글자색이 다른 부분은 내가 따로 추가한 생각 혹은 정보이다 (= 틀릴 수도 있다) 1.1 정보는 비트와 컨텍스트로 이루어진다 소스 프로그램은 byte(= 8 bit) 단위로 구성된다. 대부분의 컴퓨터 시스템은 text 문자를 아스키 표준을 사용하여 표시한다. 아스키 표준은 각 문자를 byte 길이의 정수 값으로 나타낸다. 텍스트 파일: hello.c 처럼 아스키 문자들로만 이루어진 파일 바이너리 파일: 텍스트 파일을 제외한 다른 모든 파일 컨텍스트(context) 모든 시스템 내부의 정보는 bit들로 표시됨. 서로 다른 객체들을 구분하는 유일한 방법은 이.. 2023. 10. 26.
[혼공컴운] Ch4. CPU의 작동 원리 (레지스터) 레지스터 레지스터는 CPU 내부의 작은 임시저장장치. 프로그램 속 명령어와 데이터는 실행 전후로 레지스터에 저장된다 레지스터는 앞선 ALU와 제어장치 대비 프로그래머 입장에서 더 중요하다. 우리가 개발하고 실행하는 것이 명령어, 데이터이기 때문이다. 우리는 레지스터에 담긴 값들을 관찰할 수 있다. 업무상으로도 레지스터에 담긴 값을 관찰할 일이 생각보다 많다. 로우레벨(시스템, 임베디드, 해킹 등) 개발자들은 더더욱 많다. 레지스터의 종류 CPU 내부에는 다양한 종류의 레지스터가 있고, 각각의 역할이 있다 (CPU마다 레지스터 종류와 이름이 다르기에, 일단 공통적인 것들을 일반화해서 알아두자) 프로그램 카운터 (명령어 포인터, Instruction Pointer) 메모리에서 읽어들일 명령어의 주소를 저장한.. 2023. 10. 4.