ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • chapter 1
    컴퓨터 시스템 개론 2022. 3. 5. 16:19
    728x90

    모든 작성물은

    "Computer system : A programmer's perspective", 3rd edition, Randal E. Bryant and David R. O'Hallaron 책을 참조하여 작성했습니다.

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

     

    hello.c
    hello.c 를 아스키코드로 표현

    hello.c의 표현으로 다음과 같은 근본적인 아이디어를 얻을 수 있습니다.

    모든 시스템에 있는 정보(디스크 파일, 메모리에 저장된 사용자 데이터, 네트워크를 통해 전달된 데이터)들은

    bit묶음으로 표시 됩니다.

    서로 다른 데이터 개체를 구별하는 유일한 것은 우리가 보는 것입니다.

    예를 들어 다른 개체에서 동일한 일련의 byte들은 정수, 부동소수점 숫자, 문자열 또는

    기계명령어(machine instruction)에 의해 나타납니다.

    프로그래머로서, 우리는 숫자의 machine instruction을 이해해야 합니다. 

    왜냐하면 그들은 정수와 실수와 같지 않기 때문입니다. 

     

    보통 위에서 보듯이 hello.c 는 인간이 보기에 이해가능하기 때문에 high level로 시작합니다.

    그러나 컴퓨터 시스템에서 hello.c를 실행하려면 개별적인 프로그램을 통해 low level machine language로 

    번역을 해야합니다.

    그런 다음 이러한 명령어는 실행 객체 프로그램(executable object program)이라는 형태로 package되어 

    binary disk file로 저장됩니다.

    Unix system에서는 compile driver에 의해 source file이 object file로 변환 됩니다.

    위의 과정은 컴파일 하는 과정입니다.

    여기서 gcc compiler는 source 파일 hello.c를 읽고 실행 가능한 객체 파일(executable object) hello로 변환합니다.

    4단계(Preprocessor, Compiler, Assembler, Linker) 를 보통 집합적으로 compileation system이라고 합니다.

     

    Preprocessor 단계

    Preprocessor(전처리기) cpp는 # 문자로 시작하는 원래의 C프로그램을 수정합니다.

    예를 들어 #include <stdio.h>가 있습니다. hell.c의 1번째 줄 에 있는 명령은 전처리기에게 시스템 헤더 파일

    stdio.h의 내용을 읽고 program text에 직접 삽입하도록 지시합니다.

    그 결과 확장자 파일명이 .i 가 되는 또 다른 C프로그램이 됩니다.

     

    Compile 단계

    컴파일러(compiler) cc1은 텍스트 파일 hello.i를 어셈블리 언어 프로그램을 포함하는 텍스트 파일 hello.s로 변환합니다.

    이 프로그램에는 main함수의 정의를 포함합니다.

    2-7번 째 줄은 각각 low-level machine language 명령어를 텍스트 형식으로 표현합니다.

    Assembly language는 유용합니다. 왜냐하면 어셈블리 언어는 다른 high-level language를 위한 다른 compiler에게

    공통적인 output language를 제공하기 때문입니다.

    예를 들어 C 컴파일러와 Fortran 컴파일러는 모두 동일한 Assembly language로 출력 파일을 생성합니다.

     

    Assembly 단계

    assembler(as)는 hello.s 를 machine language 명령어로 변환하여 재배치 가능한 object program(객체 프로그램)이라고

    알려진 형태로 packaging 하고 그 결과를 object file(객체 파일) hello.o 에 저장합니다.

    이 파일은 main함수 명령어를 incoding하기 위해 17 byte를 포함하는 binary file입니다.

    만약 우리가 text editor로 hello.o를 본다면 횡설수설한것처럼 보일 것입니다.

     

    Linking 단계

    hello 프로그램은 모든 C 컴파일러가 제공하는 표준 C 라이브러리의 일부인 printf 함수를 호출합니다.

    printf 함수는 printf.o 라고 하는 이미 사전에 컴파일된 object file(객체 파일)에 존재하며 

    이 파일은 hello.o 프로그램과 병합되어야 합니다.

    linker(ld) 는 이러한 병합을 처리합니다.

    그 결과 hello 파일은 메모리에 load되어 시스템에 의해 실행될 준비가 된 executable ohject file

    (실행 객체 파일 또는 단순히 실행 파일) 입니다.

    executable object program

    Unix 시스템에서 executable file(실행 가능한 파일)을 실행하려면 shell 이라는 응용프로그램을 사용합니다.

    Shell 은 프롬프트에 출력하여 사용자의 명령을 기다리는 command-line interpreter입니다.

    만약 명령줄의 첫 번째 단어가 기본 제공 shell 명령과 일치하지 않으면 shell은 load 및 실행해야하는 

    excutable file의 이름이라고 가정합니다.

    이 경우 shell은 hello 프로그램을 load 하고 실행한 다음 끌날 때 까지 기다립니다.

    hello 프로그램은 메시지를 화면에 출력한 다음 종료합니다.

    그런 다음 shell 프로프트에 출력하고 다음 입력 명령을 기다립니다.

    Hardware Organization of a System (시스템의 하드웨어 구성)

    hello프로그램을 실행할 때 어떤 일이 일어나는지 이해하기 위해, 우리는 일반적인 시스템의 하드웨어 구성을 이해할

    필요가 있습니다.

    Hardware Organization

    Bus

    전반적인 시스템 실행은 구성 요소 간에 byte들의 정보를 주고받는 Bus라고 불리는 wire에 의해 실행됩니다.

    Bus들은 일반적으로 'word' 라고 알려진 고정된 크기의 byte 덩어리들을 전송하도록 설계되어있습니다.

    한 단어의 byte 수(단어 크기)는 시스템 마다 다른 기본 시스템 매개 변수 입니다.

    오늘날 대부분의 컴퓨터는 4 byte(32 bit) 또는 8 byte (64 bit)의 워드 크기를 가지고 있습니다.

     

    I/O devices 

    입출력(I/O) 장치는 시스템이 external world와 연결하는 장치입니다. 

    예를 들어 키보드, 마우스, 모니터 디스플레이, 디스크 드라이브

    처음에는 실행파일 hello 프로그램이 디스크에 상주합니다.

    각 I/O 장치는 controller 또는 adapter를 통해 I/O Bus에 연결됩니다.

    Controller는 장치 자체 또는 시스템의 메인 출력 회로 board( = mother board)에 있는 chip set 입니다.

    Adapter는 mother board의 slot에 꽂는 카드입니다.

    결국 각각의 목적은 I/O Bus와 I/O device간에 정보를 주고 받는 것입니다.

     

    Main memory

    메인 메모리는 processor가 프로그램을 실행하는 동안 다루는 프로그램과 데이터를 모두 저장하는 임시 저장 장치

    입니다.

    물리적으로 메인 메모리는 DRAM(Dynamic Random Access Memoy) chip의 모음으로 구성됩니다.

    논리적으로 메모리는 byte의 선형 배열로 구성되면 각각 0부터 시작하는 고유한 주소(array index)를 가지고 있습니다.

    C 프로그램 변수에 해당하는 data type의 크기는 유형에 따라 다릅니다. (ex int : 4 byte, float : 4 byte, short : 2 byte)

     

    Processor or Central Processing Unit(CPU)

    중앙 처리 장치(CPU)는 메인 메모리에 저장된 명령어를 해석하거나 실행하는 엔진입니다.

    그 중심에는 PC(program counter)라고 불리는 워드 크기 저장 장치(register)가 있습니다.

    언제나 PC는 메인 메모리의 일부 machine langauage 명령어의 주소를 가지고 있습니다.

    시스템에 전원이 공급되는 시점부터 전원이 차단될 때 까지 PC가 가리키는 명령을 반복적으로 실행하고 PC를 

    업데이트 하여 다음 명령을 가리킵니다.

    Processor는 명령어 집합 아키텍쳐에 의해 정의된 매우 간단한 명령어 실행 모델에 따라 작동하는 것으로 보입니다.

    Processor는 PC가 가리키는 메모리에서 명령어를 읽고, 명령의 bit를 해석하여 명령어의 의해 지시된 간단한

    연산을 수행하고, 다음 명령어를 가리키도록 PC를 업데이트 합니다.

    이러한 간단한 연산은 몇 가지 뿐이며 메인 메모리, 레지스터 파일, 산술/논리 unit(ALU)를 중심으로 회전합니다.

    regiter file : 각각 고유한 이름을 가진 워드 크기 레지스터의 모음으로 구성된 작은 저장 장치입니다.

    ALU : 새로운 데이터와 주소값을 계산합니다.

     

    Running the "hello" Program

    위의 설명을 통해 우리는 프로그램이 어떻게 작동되는지 큰 그림을 알아보았습니다.

    사실 큰 그림 속에는 빠뜨린 detail한 부분들이 아주 많지만 쉬운 이해를 통해 먼저 큰 그림을 이해하는게 중요합니다.

     

    처음에 shell 프로그램을 통해 ./hello 입력합니다. 

    shell 프로그램은 각 항목을 register로 읽은 다음 메모리에 저장합니다.

    그 다음 우리가 enter 키를 치면 shell은 명령이 끝났다고 인지합니다.

    Reading the hello command from the keyboard.

    그러고 나서 shell은 hello 객체 파일(object file) 코드와 데이터를 Disk에서 Main memory로 복사해서 

    실행 파일(executable) hello 를 load 합니다.

    데이터에는 최종적으로 출력할 문자열 hello, world/n 이 포함됩니다.

    직접 메모리 엑세스(DMA)라고 알려진 기술을 사용하면 Processor를 통과하지 않고 Disk에서 Main memory로 

    직접 데이터를 전송합니다.

    Loading the executable from disk into main memory.

    hello 객체 파일의 코드와 데이터가 메모리에 load 되면 Processor는 hello 프로그램의 main 루틴에서 

    machine-language 명령을 실행합니다. 

    이 명령어는 hello, world/n 문자열의 byte를 메모리에 register file로, 그리고 거기서 디스플레이 장치로 복사하여

    화면에 표시합니다.

    Writing the output string from memory to the display.

     

    Caches matters

    위의 과정을 보면 데이터들이 CPU로 갖다가 메인 메모리로 갖다 Disk로 갖다 서로 데이터를 복사하면서 시간을 많이

    소모하게 됩니다.

    따라서 좀더 효율적으로 프로그램을 실행하기 위해 데이터를 복사하는 시간을 최소화 해야 합니다.

    이를 위해 메인메모리 보다 더 작고 빠른 cache memory가 등장하였습니다.

    cache memory는 Processor가 가까운 미래 내에 처리할 정보들을 미리 임시적으로 저장해놓습니다.

    L1 cache는 수만 byte를 저장하며 레지스터 파일 만큼 빠르게 접근 가능합니다.

    L1 cache 보다 수백만 byte 더큰 L2 cache는 special bus를 통해 processor와 연결 됩니다.

    processor가 L1 캐시보다 L2 캐시에 access 하는 데 5배 더 오래 걸릴 수 있지만 여전히 메인 메모리에서

    access 하는 것보다 5 ~ 10 배 더 빠릅니다.

    L1, L2 캐시는 SRAM(정적 랜덤 엑세스 메모리)으로 알려진 하드웨어 기술로 구현됩니다.

    새롭고 더 강력한 시스템에서는 L3까지 존재합니다.

    locality를 이용하여 시스템은 매우 큰 메모리와 매우 빠른 속도 둘다 얻을 수 있게 되었습니다.

    자주 접근하는 데이터를 캐시에 세팅 함으로써 빠르게 메모리 작업이 가능합니다.

    Memory hierarchy

     

    The operating system manages the hardware

    hello 프로그램이 실행되고 모니터에 hello, world가 출력되는것은 프로그램이 모니터나

    키보드에 access하는것이 아닙니다. 오히려 프로그램들은 OS에 의존합니다.

    응용프로그램들이 hardware에 access하기 위해서는 반드시 OS를 거쳐야 합니다.

    OS의 main purpose

    1) hareware가 응용프로그램에 의해 남용되지 않게 보호

    2) 복잡하고 low-level hardware장치를 조작하기 위한 간단하고 균일한 메커니즘을 응용프로그램에

    제공

    Abstraction provided by an operating system

    OS는 기본적인 abstraction(process, virtual memory, file)을 통해 위에 두가지 목표를 달성합니다.

    file = I/O 장치의 abstraction

    virtual memory = main memory, I/O 장치 모두에 대한 abstraction

    process = processor, main memory, I/O 장치에 대한 abstraction 입니다.

     

    Process

    hello와 같은 프로그램이 실행될때 OS는 hello 프로그램만 시스템에서 실행되는 것처럼 착각하게

    만듭니다. 또한 hello프로그램의 명령을 중단없이 차례로 실행하는 것처럼 보입니다.

    이러한 착시는 Process의 개념에 의해 제공됩니다.

    Process는 실행중인 프로그램을 위한 OS의 abstraction입니다.

    기존 시스템은 한번에 하나의 프로그램만 실행할 수 있지만, 새로운 멀티코어 process는 여러 프로그램을

    동시에 실행할 수 있습니다. 

    두 경우 모두 하나의 CPU가 Process switch를 사용하여 여러 process를 동시에 실행하는 것처럼 보일 수 

    있습니다.

    OS는 context switching으로 알려진 메커니즘을 사용해서 interleaving을 수행합니다.

    OS는 Process가 실행되기 위해 필요한 모든 state 정보를 추적합니다.

    Context라고 알려진 이러한 상태는 PC의 현재 값, 레지스터 파일 및 메인 메모리의 내용과 같은

    정보를 포함합니다. OS는 현재 process에서 새로운 process로 control(제어) 권한을 이전하기로

    결정하면 현재 process의 context를 저장하고 새 process의 context를 복원한 다음 control 권한을

    새 process에 전달하여 Context switch를 수행합니다. 새 process는 정확히 멈췄던 부분부터 

    시작합니다.

    process간의 전환은 OS Kernel에 의해 관리됩니다. Kernel은 항상 메모리에 상주하는 OS 코드의

    일부입니다. 응용 프로그램이 파일을 읽거나 쓰는 것과 같은 OS에 의해 어떤 조치에 필요할 때, 

    커널로 제어권을 이전합니다. 그런 다음 커널은 요청된 작업을 수행하고 응용프로그램으로 return 합니다.

    커널을 별도의 process가 아닙니다. 대신 시스템이 모든 process를 관리하기 위해 사용하는 코드와

    데이터 구조의 모음입니다.

    process를 abstraction 하려면 low-level 하드웨어와 OS 소프트웨어 간의 긴밀한 협력이 필요합니다.

     

    Thread

    일반적으로 Process가 하나의 제어흐름을 갖는다고 생각하지만 현대의 시스템에서는 process가 

    실제로 thread(스레드)라고 불리는 여러 실행 단위로 구성됩니다.

    스레드는 process의 context에서 실행되며 동일한 코드와 전역(global) 데이터를 공유합니다.

    스레드는 네트워크 서버의 동시성에 대한 요구, 다중 process간 데이터 공유가 더 쉬우며 스레드 들이

    일반적으로 process보다 더 효율적이기 때문에 점점 더 중요한 프로그래밍 모델이 되고있습니다.

    Multi-threading은 여러 processor를 사용할 수 있을 때 프로그램을 더 빠르게 실행할 수 있는 한가지

    방법입니다.

     

    Virtual Memory

    각 process는 virtual address space(가상 주소 공간) 이라고 알려진 동일한 메모리 시각을 가집니다.

    주소공간의 맨 위 영역은 모든 process에

    공통인 OS의 코드와 데이터를 위해

    예약 됩니다.

    주소 공간의 하단 영역에는 사용자의 

    Process에 의해 정의된 코드와 데이터가

    저장됩니다.

    왼쪽 그림의 주소는 아래에서 위로 증가합니다.

    각 process에서 볼 수 있는 가상 주소 공간은

    각각 특정한 목적을 가진 잘 정의된 여러영역으로

    구성됩니다.

     

     

    1. Program code and data

    코드는 모든 process에 대해 동일한 고정 주소에서 시작하여 전역(global) C 변수에 해당하는 데이터 위치를

    따릅니다.

    code and data 영역은 실행 가능한 개체파일(ex : hello 실행파일) 의 내용에서 직접 초기화 됩니다.

     

    2. Heap

    code and data영역은 힙 바로 뒤에 나옵니다. process가 실행되기 시작하면 크기가 고정된 코드와 데이터

    영역과는 달리 heap은 malloc 및 free 와 같은 C 표준 라이브러리 루틴에 대한 호출의 결과로 run time에

    동적으로 확장 및 축소 됩니다.

     

    3. Shared libraries

    주소 공간의 중간 부근에는 C 표준 라이브러리, 수학 라이브러리 등 공유 라이브러리의 코드와 

    데이터를 보관하는 영역이 있습니다. 

     

    4. Stack

    사용자의 가상 주소 공간 맨 위에는 컴파일러가 함수 호출을 구현하기 위해 사용하는 사용자 스택이

    있습니다. heap과 마찬가지로 stack은 프로그램 실행 중에 동적으로 확장 및 축소 됩니다.

    특히 함수를 호출할 때마다 stack이 커집니다. 반대로 return할때마다 stack이 수축합니다.

     

    5. Kernel virtual memory

    주소 공간의 맨 위 영역에는 Kernel이 존재합니다. 

    응용 프로그램은 이 영역의 내용을 읽거나 쓰거나 커널 코드에 정의된 함수를 직접 호출할 수 없습니다.

    대신에 이러한 작업을 수행하려면 커널을 호출해야 합니다.

     

    Files

    파일은 byte의 sequence 입니다. 모든 I/O 장치는 File로 모델링 됩니다. 

    시스템의 모든 입출력은 Unix I/O로 알려진 작은 시스템 호출 세트를 사용하여 File을 읽고 쓰는 방식으로

    수행됩니다.

    file 개념은 시스템에 포함 될 수 있는 다양한 I/O 장치를 균일한 방식으로 볼 수 있도록 application에

    제공하기 때문에 강력합니다. 

    예를 들어, 디스크 파일의 내용을 조작하는 개발자는 특정 디스크 기술에 대해 전혀 알지 못합니다. 

    또한 같은 프로그램이 다른 디스크 기술을 사용한 다른 시스템에서도 동작할 수 있습니다. 

     

    Systems Communicate with Other Systems Using Networks

    현대 시스템에서는 네트워크에 의해 다른 시스템과 연결 할 수 있습니다. 

    개인 시스템 입장으로 보면 네트워크는 단지 하나의 I/O 장치와 같이 보입니다. 

    일련의 byte를 메인메모리에서 네트워크 어뎁터로 복사했을 때, 데이터는 네트워크를 통해 

    local disk drive가 아닌 다른 시스템으로 흐릅니다. 

    마찬가지로 시스템은 다른 기계에서 전송된 데이터를 읽고 읽은 데이터를 메인 메모리에 복사 할 수 

    있습니다.

    email, World Wide Web, FTP 그리고 telnet들은 네트워크를 통해 정보를 복사하는 기능을 두는 

    application들 입니다.

     hello 프로그램을 예로 들면 컴퓨터에서 실행 중인 telnet 클라이언트를 사용하여 원격 시스템의 telnet

    서버에 연결한다고 가정합시다. 원격 시스템에 로그인 하여 shell을 실행하면 shell이 입력 명령을 수신하기

    위해 대기하고 있습니다. 이때 부터 hello 프로그램을 원격으로 실행하는 데에는 5가지 기본단계가

    포함됩니다.

    telnet 클라이언트에 hello 문자열을 입력하고 엔터 키를 누르면 클라이언트가 telnet 서버로 문자열을

    보냅니다. telnet 서버는 네트워크에서 문자열을 수신한 후 원격 shell 프로그램으로 문자열을 전달 합니다.

    다음으로 원격 shell은 hello 프로그램을 실행하고 출력 라인을 telnet서버로 다시 전달합니다. 

    마지막으로 telnet 서버는 네트워크를 통해 telnet 클라이언트로 출력 문자열을 전달합니다. 

    telnet 클라이언트는 local0 터미널에 출력 문자열을 출력합니다.

Designed by Tistory.