챕터 1은 컴퓨터 시스템에 대한 전반적인 큰 그림을 설명하는 내용이었으며 이 책에서 다룰 내용을 훑어보는 느낌입니다.

 

컴퓨터 시스템은 응용프로그램을 실행시키기 위해 하드웨어와 시스템 소프트웨어로 구성됩니다.

 

이 책의 목적은 프로그래머가 프로그램을 짤 때 각 구성 요소들이 어떻게 동작하고 그것들이 프로그램의 성능과 동작에 어떤 영향을 주는지 설명하기 위함에 있습니다. 말 그래도 프로그래머의 관점에서 컴퓨터 시스템을 바라보는 관점을 배우는 책이라고 할 수 있습니다.

 

이 책을 통해 알게 될 내용들은 아래와 같습니다.

 

  1. 컴퓨터가 숫자를 어떻게 표현하는지 배움으로써 프로그램에서 발생하는 수치적 연산의 에러를 피할 수 있다.
  2. 현대 프로세서와 메모리 시스템이 어떻게 설계되어 있는지 이해함으로써 C언어로 작성하는 프로그램을 최적화 할 수 있다.
  3. 컴파일러가 프로시저 콜을 어떻게 구현하는지를 이해함으로써 버퍼 오버플로우로 발생하는 보안적 문제를 해결할 수 있다.
  4. 링킹 과정에서 발생하는 에러를 인지하고 해결할 수 있다.
  5. 자신만의 Unix 쉘, 동적 저장공간 할당 패키지, 그리고 웹 서버를 구현할 수 있다.
  6. 멀티 프로세스 환경에서의 중요한 개념인 동시성에 대한 내용을 이해할 수 있다.

 

이제부터 "Hello World!" 출력하는 간단한 프로그램을 살펴보며 컴퓨터 시스템이 어떤식으로 동작하는지 알아볼 것입니다.

 

 

컴퓨터 시스템에서 정보는 bit와 context다.


// hello.c
#include <stdio.h>

int main() {
	printf("Hello World!\n);

	return 0;
}

위 코드는 "Hello World!"를 출력하는 간단한 c 프로그램의 소스코드입니다. 이처럼 프로그램은 처음에 소스코드의 상태로 존재합니다. 소스코드는 c 프로그램의 문법으로 작성된 단순한 텍스트 파일로 hello.c이라는 파일 이름을 갖습니다. 모든 파일은 바이트들의 나열로 구성되어 있습니다. 텍스트 파일에서 각 바이트는 ASCII 코드라는 숫자를 문자로 변환해주는 mapping 표에 기반해 하나의 문자를 나타냅니다. 이때 ASCII 코드로만 되어있는 파일을 text file이라고 하고 그 외 다른 파일들은 binary 파일이라고 합니다.

 

이처럼 컴퓨터 시스템의 모든 정보는 bit(0, 1)으로 표시됩니다. 단지 우리가 0, 1의 나열들을 어떻게 해석하느냐에 따라 int, floating-point number, character string, 혹은 machine instruction이 될 수 있습니다.

 

 

프로그램은 다른 프로그램에 의해 다른 형태로 해석된다.


hello.c는 사람이 읽을 수 있기 때문에 c로 작성된 프로그램을 high-level program이라고 합니다. 컴퓨터 시스템에서 hello.c가 실행되기 위해서는 low-level machine-language instructions으로 해석되고 executable object program이라는 형태로 패키징 되어야 합니다. 이런 executable object program으로 번역하는 작업은 compiler driver가 수행합니다. 아래는 hello.c가 실행가능한 오브젝트 파일인 hello로 번역되는 일련의 과정을 도식화한 것입니다.

 

hello.c가 hello로 번역되는 과정

 

위의 과정을 리눅스 환경에서 실행시키는 명령어는 아래와 같습니다.

gcc -c hello hello.c

각 과정에서는 다음과 같은 일이 수행됩니다.

 

  1. Preprocessing: hello.c에서 directives라고 하는 부분을 읽어들여 원본 c 파일을 변형시켜 hello.i 파일을 생성한다.
    • directives의 예시: #include <stdio.h>
  2. Compilation phase: hello.i를 어셈블리 언어 프로그램인 hello.s로 변환해서 생성한다.
  3. Assembly phase: hello.s를 기계언어로 번환하고 relocatable object program인 hello.o 파일로 변환해서 생성한다.
  4. Link phase: hello.o와 같은 오브젝트 파일끼리 합쳐서 실행가능한 오브젝트 프로그램으로 변환한다.

 

 

컴파일 시스템이 어떻게 동작하는지 알아야 하는 이유


프로그래머가 컴파일 시스템이 어떻게 동작하는지를 알아야 하는 이유는 아래와 같습니다.

 

  1. 프로그램 성능을 최적화할 수 있다.
    • 같은 동작을 하는 프로그램을 짜는 방법은 여러 개가 있습니다. 컴파일 시스템이 어떻게 동작하는지 이해한다면 프로그램을 짤 때 여러 선택지 중 코드의 성능을 최적화하는 선택지를 골라 프로그램을 짤 수 있습니다.
  2. Link-time error를 이해할 수 있다.
    • 링커가 발생시키는 에러 메시지를 해석하고 에러가 발생하는 이유를 이해해서 링크 타임에 발생한 에러를 해결할 수 있습니다.
  3. 보안적 이슈를 피할 수 있다.
    • 데이터와 제어 정보가 프로그램에 어떻게 저장되어 있는지 이해한다면 발생할 수 있는 보안적 문제를 미리 방지할 수 있습니다.

 

 

프로세서는 메모리에 저장된 명령어를 읽고 해석한다.


컴퓨터 하드웨어의 구조는 다음과 같이 구성되어 있습니다.

 

컴퓨터 하드웨어 구조

 

hello 파일이 실행할 수 있는 상태가 되면 리눅스 쉘에 아래와 같이 입력하고 Enter를 누르면 실행할 수 있습니다.

./hello

hello 프로그램이 실행되는 과정은 아래와 같습니다.

 

  1. I/O device인 keyboard에서 ./hello Enter를 치면 각 문자가 I/O Bus, I/O Bridge, System Bus, Bus interface를 거쳐 Register에 저장된 후 메인 메모리에 저장.
  2. 쉘은 실행가능한 hello file을 I/O device인 Disk로부터 읽어와 main memory에 저장.(DMA. 뒤에서 배울 내용)
  3. Main memory에 저장된 명령어는 CPU에 의해 실행되고 실행된 내용이 I/O device인 Display에 출력됨.

 

 

캐시


프로그램이 실행되는 과정을 보면 메인 메모리와 레지스터로 데이터를 복사하는 과정이 많이 일어납니다. 이는 프로그램의 성능을 떨어뜨립니다. 그리고 물리적인 이유로 용량이 큰 storage device는 용량이 작은 storage device보다 느립니다. 이렇게 용량이 큰 storage와 작은 storage간의 속도 차이를 해소하기 위해 컴퓨터 시스템에는 캐시 메모리(L1, L2, L3)라는 것이 존재합니다. 캐시에 자주 접근되는 데이터의 복사본을 저장해놓으면 용량이 큰 storage 데이터에 접근하지 않고도 용량이 더 작고 빠른 캐시를 통해 데이터를 가져올 수 있기 때문에 더 빠르게 데이터를 가져올 수 있습니다. 이처럼 캐이세 대해 잘 이해하면 프로그램의 성능을 향상시킬 수 있습니다.

 

저장공간 계층적 구조

 

 

운영체제


hello 프로그램을 실행할 때 프로그램이 직접 메인 메모리나 I/O device에 접근하지 않습니다. 프로그램은 운영체제라는 또 다른 프로그램을 통해 하드웨어 자원에 접근을 합니다. 응용프로그램이 하드웨어 자원을 조작하려면 무조건 운영체제를 통해야 한다는 점에서 운영체제는 응용프로그램과 하드웨어 사이의 레이어로 생각할 수 있습니다.

굳이 운영체제가 존재해야하는 이유는 무엇일까요? 운영체제의 목적은 아래와 같습니다.

 

  1. 원하는대로 동작하지 않는 프로그램이 하드웨어를 잘못 사용하지 않도록 함.
  2. 응용 프로그램들이 하드웨어 디바이스들을 간단하고 일관된 방법으로 조작할 수 있게 함.

 

운영체제는 위의 목적들을 process, virtual memory, file이라는 기본적인 추상화를 통해 달성합니다. 

 

  • file -> I/O device의 추상화
  • virtual memory -> main memory와 disk I/O device의 추상화
  • process -> processor, main memory, I/O device의 추상화

 

virtual memory 구조

 

 

네트워크


독립적인 컴퓨터 시스템의 입장에서 네트워크는 또 다른 I/O device일 뿐입니다.

 

 

 

Amdahl's law


 

 

추상화


컴퓨터 공학에서 추상화라는 것은 어떻게 보면 가장 중요한 개념이라고 할 수 있습니다. 추상화는 추상화의 대상이 되는 것의 구체적인 동작 및 구현을 몰라도 되게 함으로써 시스템의 복잡성을 감소시킵니다. 운영체제도 컴퓨터 하드웨어에 대한 추상화를 제공함으로써 프로그램이 하드웨어 자원을 사용할 때 구체적인 하드웨어 정보를 몰라도 되게 합니다. 

이러한 추상화는 프로그래밍 언어에서도 볼 수 있는데 여러 종류의 프로그래밍 언어들은 각각 다른 형태와 다른 레벨에서의 추상화를 제공합니다. Java의 경우는 Class가, C의 경우에는 function이 그것입니다.

  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기