- [CS:APP | WEEK 01-03] - 뒷부분 추가예정2022년 11월 10일 23시 26분 43초에 업로드 된 글입니다.작성자: nickhealthy
1. 컴퓨터 시스템으로의 여행
컴퓨터 시스템은 하드웨어와 시스템 소프트웨어로 구성되며, 이들이 함께 작동하여 응용프로그램을 실행한다.
모든 컴퓨터 시스템들은 유사한 기능을 수행하는 유사한 하드웨어와 소프트웨어 컴포넌트를 가지고 있다.💡컴포넌트란?
이들 컴포넌트들이 어떻게 동작하고, 프로그램의 성능과 정확성에 어떤 영향을 주는지 알아야 프로그램을 더 잘 개발할 수 있다고 한다.
CSAPP에서 배우는 주요 내용
- 컴퓨터가 숫자를 표시하는 방법 때문에 생기는 이상한 숫자 에러를 피하는 방법
- 최신 프로세서와 메모리 시스템의 설계를 활용하는 효과적인 기법을 사용해 C 코드를 최적화하는 방법
- 컴파일러가 프로시저 호출을 어떻게 구현하는지
- 인터넷과 네트워크 소프트웨어를 감염시키는 버퍼 오버플로우 위험성으로부터 어떻게 시스템을 보호할 수 있는지
- 유닉스 쉘, 동적 메모리 할당 패키지, 웹 서버를 작성하는 방법을 학습
- 최근 멀티 프로세서 코어들이 한 개의 칩에 집적됨에 따라 동시성의 가능성과 위험성에 대해 학습
등등.. 여러 가지를 배우게 된다고 한다.
또한 C언어에서 "Hello World!"를 출력하는 매우 간단한 프로그램이지만, 이 프로그램이 실행되어 종료되기 위해서는 시스템 주요 부분들이 각각 조화롭게 동작해야 한다. 이 책의 목적은 hello 프로그램을 실행하면 무슨 일이 일어나고, 그 이유를 이해하는 것을 도와주는 것이란다.
1-1. 정보는 비트와 컨텍스트로 이루어진다.
아래와 같은 hello 프로그램은 프로그래머가 에디터로 작성한 것을 시작으로 생명을 시작하게 되며, 이렇게 컴퓨터에 명령을 내리기 위해 사람이 알아볼 수 있도록 작성한 코드를 소스 프로그램(또는 소스파일)이라고 한다.
#include <stdio.h> int main() { printf("Hello World!"); return 0; }
이러한 소스 프로그램은 0 또는 1로 표시되는 비트들의 연속이며, byte라는 8비트 단위로 구성된다.
각 8-bit로 이루어진 바이트로 프로그램의 텍스트 문자(데이터)를 나타낸다.대부분의 컴퓨터 시스템은 텍스트 문자를 아스키(ASCII) 표준을 사용하여 표시하는데, 아스키 표준은 아래의 이미지와 같이 각 문자를 바이트 길이의 정수로 나타낸다.
hello.c의 아스키 텍스트 표시 이렇게 hello.c 파일처럼 오로지 아스키 문자들로만 이루어진 파일들을 텍스트 파일이라고 부른다. 다른 모든 파일들은 바이너리 파일이라고 한다.
hello.c 의 표시 방법은 우리가 알 수 있는 컴퓨터의 기본 개념을 잘 나타내준다.
모든 시스템 내부의 정보 - 디스크 파일, 메모리 상의 프로그램, 데이터, 네트워크를 통해 전송되는 데이터는 비트들로 표시된다. 서로 다른 객체들을 구분하는 유일한 방법은 이들을 바라보는 컨텍스트에 의해서다.
💡컨텍스트란?
컴퓨터 내에서 숫자들의 표현이 우리가 알던 정수나 실수와 같지 않기 때문에 우리는 프로그래머로서 이들에 대해 이해할 필요가 있다
1-2. 프로그램은 다른 프로그램에 의해 다른 형태로 번역된다.
hello.c 프로그램은 인간이 읽고 쓰기가 가능하게끔 하기 위해 고수준(상대적으로 사람이 알기 쉬운) C 프로그램으로 되어있다. 하지만 hello.c 프로그램을 실행하기 위해선 다른 프로그램들에 의해 저급 기계어 인스트럭션들로 번역되어야 한다. 이 인스트럭션들은 실행가능 목적 프로그램이라고 하는 형태로 합쳐져서 바이너리 디스크 파일로 저장된다. 목적프로그램은 실행가능 목적 파일이라고도 부른다.
💡인스트럭션이란?
인스트럭션(instruction)은 컴퓨터에게 일을 시키는 단위로서, 컴퓨터가 알아들을 수 있는 기계어로 이루어져 있는 명령이다.
지시 또는 명령이라고 한다.
UNIX에서 소스파일(hello.c)을 오브젝트 파일로 번역하는 과정은 컴파일러 드라이버(compiler driver)를 실행에 hello.c 텍스트 파일을 읽어들여서 실행파일인 hello로 번역한다.
전처리기, 컴파일러, 어셈블러, 링커 이 네 단계를 합쳐서 컴파일 시스템이라고 부른다.컴파일 시스템 1. 전처리 단계
전처리기(CPP)는 본래의 C 프로그램을 #문자로 시작하는 문자열 지시를 받아 수정한다.
위의 hello.c 소스 파일 첫 줄의 #include<stdio.h>는 전처리기에게 시스템 헤더파일인 stdio.h를 프로그램 문장에 직접 삽입하라고 지시한다. 그 결과로 .i로 끝나는 새로운 C 프로그램이 생성된다.2. 컴파일 단계
컴파일러(CC1)은 텍스트파일 hello.i를 텍스트 파일인 hello.s로 한번 더 번역한다. 이 파일에는 어셈블리어 프로그램이 저장된다. 이 프로그램은 main 함수의 정의를 포함하는데, 저수준 기계어 지시사항을 텍스트 형식으로 나타낸 것이다.
어셈블리어 어셈블리어는 여러 상위 수준 언어의 컴파일러들을 위한 공통의 출력언어를 제공하기 때문에 유용하다.
3. 어셈블리 단계
다음으로 어셈블러(as)가 hello.s 파일을 기계어 인스트럭션으로 번역하고, 이때 재배치가능 목적프로그램의 형태로 묶어서(패키징) 번역한다. 그리고 'hello.o'라는 목적파일에 그 결과를 저장한다.
4. 링크단계
hello 프로그램이 C 컴파일러에서 제공하는 표준 C 라이브러리(stdio.h 헤더파일)에 들어있는 printf 함수를 호출했다. 해당 함수는 이미 컴파일 된 별도의 목적파일인 printf.o에 들어 있으며, 이 파일은 hello.o 목적파일과 결합되어야 한다.
링커 프로그램(ld)가 목적 파일을 통합하는 역할을 수행한다. 그 결과 hello 파일은 실행가능 목적파일(즉, 실행파일)로 메모리에 적재되어 시스템에 의해 실행된다.
1-3. 컴파일 시스템이 어떻게 동작하는지 이해하는 것은 중요하다.
<프로그래머가 어떻게 컴파일 시스템이 동작하는지 이해해야 하는 중요한 이유 세 가지>
1. 프로그램 성능 최적화하기
최신 컴파일러들은 우수한 코드를 생성하는 좋은 툴이다. 프로그래머로서 효율적인 코드를 작성하기 위해 컴파일러의 내부 동작을 알 필요는 없지만, C 프로그램 작성 시 올바른 판단을 하기 위해서는 기계어 수준 코드에 대한 기본적인 이해를 할 필요가 있으며, 컴파일러가 어떻게 C 문장들을 기계어 코드로 번역하는지 알아야 효율적인 코드를 완성시킬 수 있기 때문이다.
2. 링크 에러 이해하기
몇몇 복잡한 프로그래밍 에러는 링커의 동작과 관련이 있으며, 특히 큰 규모의 소프트웨어 시스템을 빌드하려는 경우에 더욱 그렇다. 링커와 관련된 에러들은 실행하기 전까지 나타나지 않기 때문에 큰 규모에서도 프로그램의 안정성을 유지하려면 컴파일 시스템을 이해해야 한다.
3. 보안 약점 security holes 피하기
버퍼 오버플로우(buffer overflow) 취약성은 오랫동안 인터넷과 네트워크 상의 보안 약점의 주요 원인으로 뽑혔다. 이 취약성은 프로그래머가 신뢰할 수 없는 곳에서 획득한 데이터의 양과 형태를 주의 깊게 제한해야 할 필요를 인식하지 못해 생겨나는 문제다.
안전한 프로그래밍을 배우는 첫 단계는 프로그램 스택에 데이터와 제어 정보가 저장되는 방식 때문에 생겨나는 영향을 이해하는 것이다.
1-4. 프로세서는 메모리에 저장된 인스트럭션을 읽고 해석한다.
hello.c 소스 파일은 컴파일 시스템에 의해서 hello라는 실행 가능한 목적 파일로 번역되어 디스크에 저장되었다.
💡쉘이란?
쉘은 커맨드라인 인터프리터로 프롬프트를 출력하고,
명령어 라인을 입력 받아 그 명령을 실행한다.
만약 명령어 라인이 내장 쉘 명령어가 아니면 쉘은 실행파일의 이름으로 판단하고, 그 파일을 로딩해서 실행해 준다. 이 경우 쉘은 hello 프로그램을 메모리에 로딩하여 실행한 뒤 종료를 기다린다. hello 프로그램은 메시지를 화면에 출력 후 종료하며, 쉘은 다시 프롬프트를 출력해주고 다음 입력 명령어 라인을 기다리게 된다.
1.4.1 시스템의 하드웨어 조직
hello 프로그램을 실행할 때 무슨 일이 일어나는지 이해하기 위해서는 아래 이미지와 같은 전형적인 시스템에서의 하드웨어 조직을 이해할 필요가 있다.
시스템의 하드웨어 구성 버스(Buses)
시스템 내를 관통하는 전기적 배선군을 버스(bus)라고 하며, 컴포넌트들(위에서 각 요소) 간에 바이트 정보들을 전송한다. 버스는 일반적으로 워드(word)라고 하는 고정 크기의 바이트 단위로 데이터를 전송하도록 설계된다. 한 개의 워드를 구성하는 바이트 수는 시스템마다 보유하는 기본 시스템 변수이다.
우리가 컴퓨터 프로그램을 설치할 때 32bit인지 64bit인지 확인해야 했는데, 이때 그 bit가 바로 버스를 오고 가는 word의 사이즈이다.
입출력 장치
입출력 장치는 시스템과 외부의 연결을 담당한다. 예제에 보이는 시스템은 네 개의 입출력 장치를 가지고 있다.
- 입력용 키보드와 마우스
- 출력용 디스플레이
- 데이터와 프로그램의 장기 저장을 위한 디스크 드라이브
각 입출력 장치는 입출력 버스와 컨트롤러나 어댑터를 통해 연결된다. 각 입출력 장치는 입출력 버스를 통해 이동하며, 컨트롤러나 어탭터를 통해 연결된다. 이 두 장치의 차이는 패키징(packaging)에 있다.
- 컨트롤러: 디바이스 자체가 칩셋이거나 시스템의 인쇄기판(머더보드)에 장착된다.
- 어댑터: 머더보드의 슬롯에 장착되는 장착되는 카드이다.
위 두 개의 목적은 공통으로 입출력 버스와 입출력 장치들 간에 정보를 주고 받는 일이다.
메인 메모리
메인 메모리는 프로세서가 프로그램을 실행하는 동안 데이터와 프로그램을 모두 저장하는 임시 저장장치이다.
- 물리적 메모리: DRAM(Dynamic Random Access Memory) 칩들로 구성되어 있다.
- 논리적 메모리: 연속적인 바이트들의 배열로, 각각 0부터 시작해서 고유의 주소(배열의 인덱스)를 가지고 있다.
프로세서
주처리장치(CPU) 또는 간단히 프로세서는 메인 메모리에 저장된 인스트럭션들을 해독(실행)하는 엔진이다.
프로세서의 중심에는 워드(word) 크기의 저장장치(또는 레지스터)인 프로그램 카운터(PC)가 있다.
시스템에 전원이 공급되는 순간부터 전원이 끊어질 때까지 프로세서는 프로그램 카운터(PC)가 가리키는 곳의 인스트럭션을 반복적으로 실행하고, PC 값이 다음 인스트럭션의 위치를 가리키도록 업데이트 한다.
프로세서는 자신의 인스트럭션 집합 구조(Instruction set architecture)로 규칙적인 순서로 실행되며, 몇 개의 단순한 동작만 있다. 이들은 메인 메모리, 레지스터 파일, 수식/논리 처리기(ALU) 주위를 순환한다.
- 레지스터 파일: 각각 고유의 이름을 갖는 워드 크기의 레지스터 집합으로 구성되어 있다.
- ALU: 새 데이터와 주소 값을 계산한다.
<인스트럭션 요청에 의해 CPU가 실행하는 작업의 예>
- 적재(Load): 메인 메모리에서 레지스터에 한 바이트 또는 워드를 이전 값에 덮어쓰는 방식으로 복사
- 저장(Store): 레지스터에서 메인 메모리로 한 바이트 또는 워드를 이전 값을 덮어쓰는 방식으로 복사
- 작업(Operate): 두 레지스터의 값을 ALU로 복사하고, 두 개의 워드로 수식연산을 수행한 뒤, 결과를 덮어쓰기하는 방식으로 레지스터에 저장
- 점프(Jump): 인스트럭션 자신으로부터 한 개의 워드를 추출하고, 이것을 PC에 덮어쓰기 방식으로 복사
1-5. 캐시가 중요하다.
<hello 프로그램의 실행 순서>
- 하드디스크에서 hello 프로그램의 기계어 인스트럭션들을 로딩 및 메인 메모리에 복사
- 프로세서가 프로그램을 실행할 때 인스트럭션들은 메인 메모리에서 프로세서로 복사
- 마찬가지로 "hello, world\n" 데이터 스트링도 디스크에 저장되어 있었지만, 메인 메모리로 복사되었다가 디스플레이 장치로 복사 및 출력된다.
위의 여러 복사 과정들 때문에 우리가 얻을 수 있는 중요한 교육은 시스템이 정보를 한 곳에서 다른 곳으로 이동시키는 일에 많은 시간을 할애한다는 것이다. 이러한 이유 때문에 시스템 설계자들의 주요 목적은 이러한 복사 과정들을 가능한 한 빠르게 동작하도록 하는 것이다.
물리학의 법칙으로 인해 더 큰 저장장치들은 보다 작은 저장 장치들 보다 더 느린 속도를 가지게 된다고 한다.(물리학의 법칙도 컴퓨터 과학에 들어간다니 신기하다..) 그리고 더 빠른 장치들은 보다 더 느린 장치들 만드는 데 더 많은 비용이 든다.
시스템 설계자들은 이러한 격차를 줄이기 위해(프로세서 - 메모리 간 격차에 대응) 보다 작고 빠른 캐시 메모리(간단히 캐시)라고 부르는 저장장치를 고안하여 프로세서가 단기간에 필요로 할 가능성이 높은 정보를 임시로 저장할 목적으로 사용한다.
보통 L1, L2, L3 캐시로 구분되어 있으며, 앞의 숫자일수록 고성능의 캐시이며, 그만큼 저장 공간은 작다.
캐시 시스템의 이면에 깔려 있는 아이디어는 프로그램이 지엽적인 영역의 코드와 데이터를 액세스하는 경향인 지역성(locality)를 활용하여 빠른 메모리 효과를 얻을 수 있다는 것이다. 또한 캐시는 SRAM(static Random Access Memory)이라는 하드웨어 기술을 이용해 구현한다.💡램(RAM)
램은 휘발성 메모리로 한시적으로 모듈에 저장된 정보는 컴퓨터가 종료될 시 삭제된다.
또한 램의 저장 방식에 따라 DRAM, SRAM으로 나뉜다.
캐시 메모리 1-6. 저장장치들은 계층 구조를 이룬다.
모든 컴퓨터 시스템의 저장장치들은 아래 이미지와 같은 메모리 계층구조로 구성되어 있다.
계층의 꼭대기에서부터 마지막까지 내려갈수록 저장장치들은 더 느리고, 더 크고, 바이트 당 가격이 싸진다.- 레지스터 파일은 계층구조의 최상위인 레벨0 | L0
- 캐시 메모리는 레벨 1 - 3 | L1 - L3
- 메인 메모리는 레벨 4 | L4
메모리 계층구조의 예 메모리 계층구조의 주요 아이디어는 한 레벨의 저장장치가 다음 하위레벨 저장장치의 캐시 역할을 한다는 것이다.
1-7. 운영체제는 하드웨어를 관리한다.
운영체제(Operation System)가 제공하는 서비스를 활용해 하드웨어를 제어한다. hello 프로그램을 실행할 때, 쉘 프로그램에서 hello 프로그램을 로딩하고, 프로그램 메시지를 출력할 때 프로그램이 키보드나 디스플레이, 디스크나 메인메모리를 직접 엑세스하지 않고도 가능했던 이유는 운영체제 덕분이다.
운영체제는 하드웨어와 소프트웨어 사이에 위치한 소프트웨어 계층으로 생각할 수 있으며, 응용 프로그램이 하드웨어를 제어하려면 언제나 운영체제를 통해 하드웨어를 제어할 수 있다.
컴퓨터시스템의 계층화모습 <운영체제의 주요 목적 2가지>
- 제멋대로 동작하는 응용 프로그램들이 하드웨어를 잘못 사용하는 것을 막기 위해
- 응용 프로그램들이 단순하고 균일한 매커니즘을 사용하여 복잡하고 매우 다른 저수준 하드웨어 장치들을 조작할 수 있도록 하기 위해
운영체제는 위 두 가지 목표를 달성하기 위해 근복적인 추상화를 사용한다.
아래 이미지에서 나오는 것처럼 프로세스, 가상메모리, 파일을 모두 추상화의 결과이다.운영체제에 의한 추상화 1.7.1 프로세스
프로세스는 실행 중인 프로그램에 대한 운영체제의 추상화이다. 이전 시스템들은 한 번에 한 개의 프로그램만 실행 가능했지만, 요즘의 멀티코어 프로세서들은 여러 개의 프로그램을 동시에 실행 가능하게 해준다. 어느 쪽이건 프로세서가 프로세스들을 바꿔주는 방식으로 한 개의 CPU가 다수의 프로세스를 동시에 실행하는 것처럼 보이게 해준다.
운영체제는 문맥 전환(context switching)이라는 방법을 사용해 이러한 교차실행을 수행한다.
운영체제는 프로세스가 실행하는 데 필요한 모든 상태정보의 변화를 추적한다. 이 컨텍스트라고 부르는 상태정보는 PC, 레지스터 파일, 메인 메모리의 현재 값을 포함한다. 어느 한 순간에 단일 프로세서 시스템은 한 개의 프로세스의 코드만을 실행할 수 있다. (즉, 결론적으로 동시에 실행하는 것처럼 보여도 단일 프로세서로 구성된 시스템은 한 개의 프로세스만을 동작시킬 수 있다는 말임.)운영체제는 현재 프로세스에서 다른 프로세스로 제어를 옮기려고 할 때, 현재 프로세스의 컨텍스트를 저장하고, 새 프로세스의 컨텍스트를 복원시키는 문맥 전환을 통해 제어권을 다른 프로세스로 넘긴다.
이처럼 하나의 프로세스에서 다른 프로세스로의 전환은 운영체제의 커널(kernel)에 의해 관리된다. 커널은 운영체제 코드의 일부분으로 메모리에 상주한다. 커널은 모든 프로세스를 관리하기 위해 시스템이 이용하는 코드와 자료구조의 집합이다. 위와 같은 프로세스 추상화를 구현하기 위해서는 저수준의 하드웨어와 운영체제 소프트웨어가 함께 긴밀하게 협력해야 한다.프로세스 문맥전환 1.7.2 쓰레드(Thread)
프로세스는 마치 한 개의 제어흐름을 갖는 것 같지만, 프로세스는 실제로 쓰레드라고 하는 다수의 실행유닛으로 구성되어 있다.
각각의 쓰레드는 해당 프로세스의 컨텍스트에서 실행되며, 동일한 코드와 전역 데이터를 공유한다.
쓰레드는 프로그래밍 모델로서의 중요성이 더욱 커지고 있는데, 그 이유는- 다수의 프로세스들에서 보다 데이터의 공유가 더 쉽다.
- 쓰레드가 프로세스보다 더 효율적이다.
1.7.3 가상메모리
가상 메모리는 각 프로세스들이 메인 메모리 전체를 독점적으로 사용하는 것 같은 환상을 제공하는 추상화이다.
각 프로세스는 가상주소 공간이라고 하는 균일한 메모리의 모습을 갖게 된다.아래의 그림은 리눅스에서 각 프로세스들이 가상주소 공간을 나타내고 있다.(다른 운영체제에서도 비슷한 형식이라고 한다.) 리눅스에서, 주소공간의 최상위 영역은 모든 프로세스들이 공통으로 사용하는 운영체제의 코드와 데이터를 위한 공간이다.(확실하지는 않지만, 커널 제어 및 시스템 콜을 위한 영역인 것 같다.) 주소는 아래에서 위로 올라갈수록 주소 값이 증가한다.
<가상주소 공간(가상메모리)의 영역 구분>
- 프로그램 코드와 데이터: 모든 프로세들이 같은 고정 주소에서 시작하며, C 전역변수에 대응되는 데이터 위치들이 따라온다. 코드와 데이터 영역은 실행 가능 목적파일인 hello로부터 직접 초기화된다.
- 힙(Heap): 다음으로 런타임 힙이 따라온다. 크기가 고정되어 있는 코드와 데이터 영역과는 다르게 힙은 프로세스가 실행되면서 C 표준함수인 malloc이나 free를 호출하면서 런타임에 동적으로 크기가 늘었다 줄었다 한다.
- 공유 라이브러리: 공유 라이브러리의 코드와 데이터를 저장하는 영역이다. (printf, scanf 등)
- 스택(Stack): 가상 메모리 맨 위에 위치한 컴파일러가 함수 호출을 구현하기 위해 사용하는 사용자 스택이 위치한다. 힙과 마찬가지로 스택은 프로그램이 실행되는 동안 동적으로 크기를 조절하며, 특히 함수를 호출할 때마다 스택이 커진다.
- 커널 가상메모리: 주소공간의 맨 윗부분은 커널을 위해 예약되어 있다. 응용 프로그램들은 이 영역의 내용을 읽거나 쓰는 것이 금지, 커널 코드 내에 정의된 함수를 직접 호출하는 것도 금지 되어 있다. 대신, 이런 작업을 수행하기 위해 커널을 호출해야 한다.
<프로세스의 중요 동작 아이디어>
가상 메모리가 동작하기 위해서는 프로세서가 만들어내는 모든 주소를 하드웨어로 번역하는 등 하드웨어와 운영체제의 긴밀한 상호작용이 필요하다.
- 프로세스의 가상메모리의 내용을 디스크에 저장하고,
- 메인 메모리를 디스크를 캐시로 사용하는 것이다.
- 앞에서 저장장치는 모두 계층 구조이며, 그 다음 상위 수준의 저장장치 계층을 캐시로 사용한다고 했었다.
프로세스의 가상주소공간 1.7.4 파일
파일은 더도 말고 덜도 말고 연속된 바이트들이다. 디스크, 키보드, 디스플레이, 네트워크까지 포함하는 모든 입출력 장치는 파일로 모델링한다. 시스템의 모든 입출력은 유닉스 I/O라는 시스템 콜들을 이용하여 파일을 읽고 쓰는 형태로 이루어진다. 파일 추상화는 시스템에 들어있는 다양한 입출력 장치들의 통일된 관점으로 응용 프로그램에 제공한다는 점에서 매우 유용하고 중요하다.
1-8. 시스템은 네트워크를 사용하여 다른 시스템과 통신한다.
최근 시스템들은 네트워크에 의해 다른 시스템과 종종 연결된다. 이러한 개별 시스템의 관점에서 볼 때, 네트워크는 아래의 이미지처럼 또 다른 입출력 장치로 볼 수 있다. 시스템이 메인 메모리로부터 네트워크 어댑터로 일련의 바이트를 복사할 때, 데이터는 로컬 디스크 드라이브 대신 네트워크를 통해 다른 컴퓨터로 이동된다. 마찬가지로 시스템은 다른 컴퓨터로부터 받은 데이터를 읽어서 메인 메모리에 복사할 수 있다.
네트워크는 일종의 입출력장치이다. 인터넷과 같은 글로벌 네트워크의 출현으로 다른 컴퓨터로 정보를 복사(송신)하는 것은 가장 중요한 컴퓨터의 응용이 되었다. 일례로 이메일, 메신, FTP, Telnet 등과 같은 응용 프로그램들이 네트워크를 통해 정보를 복사하는 기능을 사용하는 것이다. 아래는 hello 프로그램을 telnet 프로그램을 사용하여 원격으로 실행하는 과정을 보여준다.
telnet을 사용하여 hello 프로그램을 네트워크상에서 원격으로 실행 이러한 유형의 클라이언트와 서버 간의 데이터 교환은 모든 네트워크 응용의 전형적인 사례이다.
1-9. 중요한 주제들
위의 설명들을 통해 우리는 시스템이라는 것이 단지 하드웨어를 뜻하는 것은 아니라는 것을 알 수 있었다.
중요한 사실은 응용 프로그램의 실행이라는 궁긍의 목적을 달성하기 위해 협력해야 하는 하드웨어와 시스템 소프트웨어가 서로 연결된 것을 말한다.
앞으로 하드웨어와 소프트웨어의 중요 세부 내용을 배우게 되면서 어떻게 보다 빠르고, 안정적인 프로그램을 작성할 수 있는지 깨달을 수 있다고 한다.
Ref
다음글이 없습니다.이전글이 없습니다.댓글