본문 바로가기

운영체제

[Computer Systems] A Tour of Computer Systems

1.1 Information Is Bits + Context

대부분의 컴퓨터는 문자를 ASCII를 이용해 나타낸다.

ASCII는 각각의 문자(character)를 byte-size integer로 나타낸다.

소스파일은 ASCII로 변환된 sequence of bytes로 저장되어있다.

ASCII characters로만 이뤄져있는 파일은 text files이다.

다른 파일은 binary files이다.

시스템에서 모든 정보는 bit들로 표현된다. 이들을 식별할 수 있는 방법은 context이다.

1.2 Programs Are Translated By Other Programs into Different Forms

high-level의 C 프로그램을 실행하기 위해서는 low-level의 machine-language instructions의 연속으로 변환되어야 한다. 이 instructions는 executable object program(exceutable object files)라는 형태로 packaged된다. 그리고 디스크에 binary로 저장된다.

Unix system에서 compiler driver가 source file을 object file로 변환시킨다.

gcc는 컴파일러 드라이버이다.

linux> gcc -o hello hello.c

변환은 다음 4단계에 걸쳐 이뤄진다. 이 4단계를 collectively compilation system이라고 한다.

  1. Preprocessing phase
    preprocessor(cpp)가 C 프로그램을 # 문자로 시작하는 directives에 따라 변환한다. 예를 들어 #include <stdio.h> 는 preprocessor가 시스템 헤더 파일 stdio.h를 읽어서 프로그램에 insert하라고 한다. 그 결과 .i suffix의 C 프로그램이 생성된다.
  2. Compilation phase
    2-7번째 라인은 하나의 low-level machine language instruction이다.
    compiler(cc1)는 text file hello.i를 assembly-language program hello.s로 변환한다.
    main: subq $8, %rsp movl $.LC0, %edi call puts movl $0, %eax addq $8, %rsp ret
  3. Assembly phase
    hello.s를 machine language instructions로 변환하고 relocatable object program으로 package하여 hello.o파일로 만든다.
  4. Linking phase
    hello 프로그램은 C 컴파일러가 제공하는 standard C library의 printf 함수를 부른다. printf 함수는 별개의 미리 컴파일된 object file printf.o에 있다. printf.o파일은 hello.o프로그램과 merge되어야 한다. linker가 이 merging을 한다. 그 결과 executable object file인 hello파일이 생성된다.

1.3 It Pays to Understand How Compilation Systems Work

컴파일레이션 시스템의 작동 방식을 알아야 하는 이유

  • Optimizing program performance
  • Chapter3, 5, 6에서 공부한다.
  • Understanding link-time errors
  • Chapter7에서 공부한다.
  • Avoiding security holes
  • stack discipline과 buffer overflow vulnerabilities를 Chapter3에서 공부한다.

1.4 Processors Read and Interpret Instructions Stored In Memory

executable object file을 실행시키려면, shell에 파일 이름을 입력한다. shell은 prompt를 출력하는 command-line interpreter이다.

linux> ./hello
hello, world
linux>

디스크에 저장되어 있는 executable object file인 hello 프로그램을 실행시킨다.

1.4.1 Hardware Organization of a System

Bus

버스는 컴포넌트 사이에서 words(정해진 사이즈의 bytes)를 이동시킨다.

I/O Device

I/O Device는 바깥 세상과 시스템의 연결이다. 각각의 I/O Device는 controller나 adapter에 의해 I/O bus와 연결되어있다. Controller는 디바이스 자체의 칩셋이거나 motherboard라고 하는 시스템의 main printed circuit board에 있는 칩셋이다. Adapter는 motherboard의 slot에 플러그될 수 있는 카드이다. Controller와 Adapter는 I/O Bus와 I/O Device 사이에서 정보를 전달한다.

Main Memory

프로세서가 프로그램을 실행중일 때 프로그램과 데이터를 저장하고 있는 temporary storage device이다. 물리적으로(physically) 메인 메모리는 DRAM을 가지고 있다. 논리적으로(logically) 메모리는 linear array of bytes로 organized되어있다. 각각은 unique address를 가진다. 일반적으로 각각의 machine instructions는 variable number of bytes(가변 바이트 수?)로 구성된다. C 프로그램의 variables와 일치하는 데이터 아이템의 사이즈는 타입에 따라 다르다. 예를 들어, 리눅스를 실행하는 x86-64 머신에서는, short type은 2byte, int와 float type은 4byte, long과 double type은 8byte이다.

Processor

Central Processing Unit(CPU) 또는 processor는 메인 메모리에 저장된 instructions를 interpret하는 engine이다. 코어에는 program counter(PC)라고 하는 word-size의 storage device(register)가 있다. PC는 언제나 메인 메모리에 있는 machine-language instruction을 가리킨다.

파워가 들어올 때 부터 닫힐 때 까지, 프로세서는 반복적으로 PC가 가리키는 instruction을 실행한다. 그리고 다음 instruction을 가리키도록 PC를 업데이트한다. 프로세서는 instruction set architecture가 정의하는 instruction execution model에 따라 작동된다. 이 모델에서 instructions는 연속적으로 실행되고, 하나의 instruction 실행은 몇가지 단계를 거친다. 프로세서는 PC가 가리키는 instruction을 읽는다. bits를 interpret한다. instruction이 가리키는 operation을 실행한다. 그리고 PC pointer를 update한다.

operation은 메인 메모리, 레지스터 파일 ALU을 사용한다. 레지스터 파일은 word-size의 레지스터로 구성되어 있고 각각이 unique name을 가진 작은 storage device이다. ALU는 새로운 데이터와 address value를 계산한다. 다음은 CPU가 instruction에 대해 수행하는 operation의 예시이다.

  • Load: main memory → register로 word를 복사한다.
  • Store: register → main memory 로 word를 복사한다.
  • Operate: 두개의 레지스터의 contents를 ALU에 복사한다. 두 word에 대해 arithmetic operation을 실행한다. 그리고 결과를 register에 저장한다.
  • Jump: instruction에서 word를 추출하여 PC에 복사한다.

1.4.2 Running the hello Program

shell program은 입력한 command의 instructions를 실행한다. ./hello 를 입력하면 shell program은 하나씩 읽어서 memory에 저장한다.

enter key를 입력하면, shell은 입력이 끝났다는 것을 알게된다. 그리고나서 executable hello를 file disk에서붙너 main memory로 load한다. (hello object file의 코드와 데이터를 복사하는 instructions실행한다.) DMA(Direct Memory Access)를 사용해 processor를 사용하지 않고 데이터를 disk에서 main memory로 옮긴다.

hello object file의 code와 data가 메모리에 load되면, processor는 hello program의 main routine에 있는 machine-language instructions를 실행한다.

1.5 Caches Matter

이 예제에서 알 수 있는 점은 컴퓨터 시스템이 information을 옮기는 데 많은 시간을 사용한다는 것이다. 프로그래머의 관점에서 복사는 프로그램의 real work를 느리게 하는 오버헤드이다. 그래서 시스템 디자이너의 major goal은 copy operations를 빠르게 만드는 것이다.

physical laws에 의해 큰 storage device는 느리다. 그리고 빠른 storage device는 비싸다.

전형적인 레지스터 파일은 a few hundred bytes의 정보를 저장한다. 메인 메모리는 billions of bytes를 저장한다. 하지만 프로세서는 레지스터 파일을 메모리보다 100배 빨리 읽을 수 있다. 더 문제인 것은, 반도체 기술이 발달함에 따라 이 processor-memory gap이 점점 커진다는 것이다. 프로세서를 빠르게 만드는 것이 메인 메모리를 빠르게 만드는 것 보다 쉽다.

processor-memory gap을 다루기 위해 시스템 디자이너들은 작고 빠른 storage device, 프로세서가 가까운 미래에 필요로 할 정보를 위한 temporary staging areas인 cache memories를 고안하게 되었다.

L1 cach는 tens of thousands of bytes를 가질 수 있다. L2 cache는 hundreds of thousands to millions of bytes를 가질 수 있다. L1 cache보다 5배 더 걸린다. 하지만 main memory보다 5 to 10배 빠르다. L1 cache와 L2 cache는 static random access memory(SRAM)으로 구현되어있다.

1.6 Storage Devices From a Hierarchy

memory hierarchy의 main idea는 한 레벨의 storage가 다음 레벨의 storage에 캐시로 쓰인다는 것이다. Register files는 L1의 cache이고 L1은 L2의 cache이다. 분산 파일 시스템의 네트워크 시스템에서는 local disk가 다른 시스템의 disk의 cache로 작용한다.

1.7 The Operating System Manages the Hardware

hello 예제에서 hello program을 로드하고 실행시킬 때, 그리고 hello program이 메세지를 print할 때, 프로그램이 키보드, 디스플레이, 디스크, 또는 메인 메모리 그 어느것도 직접 접근하지 않았다. 장치들이 운영체제가 제공하는 서비스에 의존한다. Operating system이 어플리케이션 프로그램과 하드웨어 사이에 놓여진 레이어라고 생각할 수 있다. 하드웨어를 manipulate하려는 모든 어플리케이션 프로그램은 operating system을 통해 사용할 수 있다.

Operating sytem은 두가지 목적이 있다. 1) runaway applicatoins에 의한 하드웨어의 misuse를 막는다. 2) 어플리케이션에 simple하고 동일한 mechanisms을 제공한다. Operating system은 이 목적을 fundamental abstractions(processes, virtual memory, and files)를 통해 달성한다.

Files는 I/O devices를 위한 abstractions이다. Virtual memory는 main memory와 I/O devices를 위한 abstractions이다. Processes는 processor, main memory, I/O devices를 위한 abstractions이다.

1.7.1 Processes

hello와 같은 프로그램이 모던 시스템에서 작동될 때, operating system은 프로그램이 시스템에서 작동하는 하나의 프로그램이라는 착각(illusion)을 제공한다. 프로그램은 processor, main memory, I/O devices에 exclusive use를 가지고 있는 것 처럼 보인다. Processor는 instructions를 interruption없이 한번에 하나씩 실행하고 있는 것 처럼 보인다. code와 data는 시스템의 memory의 only objects인 것 처럼 보인다. 이 착각은 notion of process이 제공한다.

A process is the operating system’s abstraction for a running program. 프로세스는 실행중인 프로그램의 추상화이다.

하나의 CPU가 프로세스를 스위치해가며 concurrently 여러개의 프로세스를 실행시킬 수 있다. operating system이 interleaving하는 것을 context switching이라고 한다. concurrently는 한 프로세스의 instructions가 다른 프로세스의 instructions으로 interleaved된다는 것이다. By concurrently, we mean that the instructions of one process are interleaved with the instructions of another process.

operating system은 프로세스가 실행하기 위해 필요한 state information을 추적한다. 이 state는 context라고도 한다. PC의 현재 값이나 register file, 그리고 main memory의 contents들이다. operating system이 control을 다른 프로세스로 옮길 때, 현재 프로세스의 context를 저장하고 새로운 프로세스의 context를 restore 하는 context switch를 진행한다.

1.7.2 Threads

각각의 스레드는 프로세스의 context에서 실행되고 코드와 글로벌 데이터를 공유한다. 스레드에서 데이터를 공유하는 것이 프로세스에서 데이터를 공유하는 것 보다 쉽기 떄문에 스레드는 많이 사용된다.

1.7.3 Virtual Memory

Virtual memory is an abstraction that provides each process with the illusion that it
has exclusive use of the main memory. 각각의 프로세스는 메모리에 대해 virtual address space라는 동일한 view를 가진다.

virtual address space에는 area가 나뉘어있다.

  • Program code and data
  • Heap
  • Shared libraries
  • Stack
  • Kernel virtual memory

1.7.4 Files

file은 sequence of bytes이다. 모든 I/O device는 file로 모델되어있다. 시스템의 모든 Input과 output은 file read, write를 통해 이루어진다.

1.8 Systems Communicate with Other Systems Using Networks

1.9 Important Themes

1.9.2 Concurrency and Parallelism

Thread-Level Concurrency

Hyperthreading, 또는 simultaneous multi-threading은 하나의 CPU에서 multiple flows of control을 실행하는 technique이다. PC나 레지스터 파일과 같은 CPU 하드웨어의 multiple copies를 가지고 floating-point arithmetic을 실행하는 unit은 single copies를 가진다. 과거의 프로세서는 스레드를 shift하는 데 20,000 clock cycles가 걸렸지만, hyperthreaded thread는 cycle-by-cycle basis로 다른 스레드를 실행한다. Intel Core i7 프로세서는 하나의 코어가 두개의 thread를 실행할 수 있다.

멀티프로세싱은 두 방안에서 시스템 퍼포먼스를 향상시킨다. 첫 번째로 multiple tasks를 실행할 때 coucurrency를 simulate할 필요가 감소된다. 두 번쨰로, 여러개의 스레드가 동시에 효과적으로 실행될 수 있을 때 하나의 어플리케이션을 빠르게 실행할 수 있다.

Instruction-Level Parallelism

instruction-level parallelism의 특성을 활용해서 현대의 프로세서는 2-4 instructions를 하나의 clock cycle에 실행시킬 수 있다. 어떤 instruction은 20사이클을 필요로 하지만, 프로세서는 trick을 사용해 한 번에 100개의 instructions를 처리한다. Chapter4의 pipelining에서 이를 배울 것이다.

Single-Instruction, Multiple-Data (SIMD) Parallelism

Single-Instruction, Multiple-Data (SIMD) Parallelism 이라는 하드웨어가 있따. 하나의 instruction이 multiple operations을 동시에 수행할 수 있또록 한다.

1.9.3 The Importance of Abstractions in Computer Systems

추상화는 컴퓨터 사이언스에서 매우 중요한 개념이다. instruction set architecture는 프로세서 하드웨어의 추상화를 제공한다. 이 추상화는 machine-code 프로그램이 한번에 하나의 instruction을 수행하는 프로세서에서 실행된 것 처럼 한다. 하드웨어는 여러개의 instructions를 parallel로 실행한다.

'운영체제' 카테고리의 다른 글

Segment와 Paging  (0) 2023.07.29