728x90
컴퓨터 시스템 책을 읽고 정리한 글입니다
정보는 비트와 컨텍스트로 이루어진다
프로그래머가 작성한 소스 프로그램은 hello.c라는 텍스트 파일로 저장된다.
소스 프로그램은 0또는 1로 표현되는 비트들의 연속이며, byte라는 8bit 단위로 구성되고,
각 바이트는 프로그램의 텍스트 문자를 나타낸다.
대부분의 컴퓨터 시스템은 텍스트를 아스키(ASCII) 표준을 사용해 표시한다.
아스키 표준은 각 문자를 바이트 길이의 정수값으로 나타낸다.
오로지 아스키 문자들로만 이뤄진 파일을 '텍스트 파일'이라고 부른다.
다른 파일들은 '바이너리 파일'이라고 한다.
프로그램은 다른 프로그램에 의해 다른 형태로 번역된다
사람이 작성한 소스 코드는 기계어 인스트럭션들로 번역되어야 한다.
(instruction - 지시, 설명 / 명령, 명령어 등으로 이해하면서 보면 좋을 것 같다)
이 명령들은 실행가능 목적 프로그램이라는 형태로 합쳐져 바이너리 디스크 파일로 저장된다.
컴파일러 드라이버는 유닉스 시스템에서 소스파일에서 오브젝트 파일로 번역한다.
linux> gcc -o hello hello.c
너무 익숙한 문장이다 ㅋㅋ
컴파일러 드라이버가 소스 파일을 읽어 실행하기까지 4단계를 거친다.
전처리기 - 컴파일러 - 어셈블러 - 링커
이 4단계를 실행하는 프로그램을 합쳐서 컴파일 시스템이라고 한다.
- 전처리 단계: 전처리기(cpp)는 c 프로그램을 #문자로 시작하는 디렉티브(directive)에 따라 수정한다.
#include <stdio.h> 문구는 전처리기에게 시스템 헤더 파일을 프로그램에 직접 삽입하라고 지시한다.
전처리가 끝난 파일은 .i 파일로 생성된다. - 컴파일 단계: 컴파일러(ccl)는 텍스트 파일 .i를 텍스트 파일 .s로 번역하며,
.s 파일에는 번역된 어셈블리어 프로그램이 저장된다. 어셈블리어는 저수준 기계어 명령어이다. - 어셈블리 단계: 어셈블러(as)는 .s를 기계어 인스트럭션으로 번역하고,
이들을 재배치가능 목적프로그램으로 묶어 .o라는 목적 파일에 결과를 저장한다.
.o 파일은 인스트럭션들을 인코딩하기 위한 바이너리 파일이다. - 링크 단계: 작성한 c 프로그램이 printf 같은 표준 C라이브러리에 포함된 함수를 호출한다면
이 단계에서 호출된다. printf는 이미 컴파일 된 목적 파일인 printf.o에 들어 있으며,
링커 프로그램(ld)이 이 파일을 우리가 작성한 파일과 통합하는 작업을 수행한다.
이 결과인 파일은 실행가능 목적파일(즉, 실행파일)로 메모리에 적재되어 시스템에 의해 실행된다.
컴파일 시스템이 어떻게 동작하는지 이해하는 것은 중요하다
- 프로그램 성능 최적화하기
컴파일 시스템의 동작을 이해하는 것으로 저 최적화된 프로그램을 작성할 수 있다.
switch와 if-else는 서로 어떤 상황에서 더 유리한지?
while이 for루프보다 효율적인지?
수식 연산시 괄호를 단순히 재배치한 것으로 함수가 빨리 실행되는 이유는? 등등을 이해해야한다... - 링크 에러 이해하기
- 보안 약점 피하기
안전한 프로그래밍을 배우는 첫 단계는 프로그램 스택에 데이터와 제어 정보가 저장되는 방식 때문에 생겨나는 영향을 이해하는 것이다.
프로세서는 메모리에 저장된 인스트럭션을 읽고 해석한다
- 버스 : 시스템 내를 관통하는 전기적 배선군을 버스라고 하며, 컴포넌트들 간에 바이트 정보를 전송한다.
버스는 워드(word)라고 하는 고정 크기의 바이트 단위로 데이터를 전송하도록 설계된다.
한 개의 워드를 구성하는 바이트 수는 시스템마다 보유하는 기본 시스템 변수.
시스템에 따라 4바이트(32비트) 또는 8바이트(64비트)의 크기를 갖는다. - 입출력 장치 : 각 입출력 장치는 입출력 버스와 컨트롤러나 어댑터를 통해 연결된다.
이 두 장치의 차이는 패키징에 있다.
컨트롤러는 디바이스 자체가 칩셋이거나 시스템의 인쇄기판(머더보드)에 장착됨
어댑터는 머더보드의 슬로에 장착되는 카드임
이들의 목적은 입출력 버스와 입출력 장치 사이에 정보를 주고 받도록 해주는 일이다. - 메인 메모리 : 메인 메모리는 프로세서가 프로그램을 실행하는 동안 데이터와 프로그램을 모두 저장하는 임시 저장장치다. 메인 메모리는 물리적으로 DRAM(동적 랜덤 액세스 메모리) 칩들로 구성되어 있다. 논리적으로 메모리는 연속적인 바이트들의 배열로, 각각 0부터 시작해서 고유의 주소를 가지고 있다.
- 프로세서 : 프로세서 또는 CPU(주처리장치)는 메인 메모리에 저장된 인스트럭션을 실행하는 엔진이다.
프로세서의 중심에는 워드 크기의 저장장치(또는 레지스터)인 PC(프로그램 카운터)가 있다. 이 카운터는 메인 메모리의 기계어 인스트럭션을 가리킨다.
프로세서는 PC가 가리키는 메모리로부터 명령을 읽어오고, 인스트럭션에서 비트들을 해석하고, 인스트럭션이 지정하는 동작을 실행하고, PC를 다음 인스트럭션 위치로 업데이트 한다. PC의 새로운 위치는 메모리 상에서 연속적일 수도 있고, 그렇지 않을 수도 있다.
다음은 CPU가 동작하는 작업의 예
- 적재(Load) : 메인 메모리 -> 레지스터로 한 바이트 또는 워드를 이전 값에 덮어쓰는 방식으로 복사
- 저장(Store) : 레지스터 -> 메인 메모리로 한 바이트 또는 워드를 이전 값에 덮어쓰는 방식으로 복사
- 작업(Operate) : 두 레지스터 값을 ALU(Arithmetic / Logic Unit)로 복사하고 두 개의 워드를 수식 연산을 수행한 뒤,
결과를 덮어쓰기 방식으로 레지스터에 저장 - 점프(Jump) : 인스트럭션 자신으로부터 한 개의 워드를 추출하고, 이것을 PC에 덮어쓰기 방식으로 복사
잘 안 외워져서 열심히 써봤는데 여전한 것 같다...
'컴퓨터시스템' 카테고리의 다른 글
웹서버와 CGI와 WAS (+ MIME Type) (2) | 2024.02.22 |
---|---|
파일 디스크립터란? (File Descriptor) (0) | 2024.02.22 |
메모리 단편화와 메모리 할당 정책 (0) | 2024.02.07 |
GCC(GNU Compiler Collection)란? (0) | 2024.02.01 |
C언어) 포인터와 주소 연산자 (0) | 2024.01.26 |