이번주 미니프로젝트를 끝내고 조가 바뀌고 WEEK00에서 넘어가면서 WEEL01 컴퓨팅사고로의전환이 주제다.
WEEK01은 알고리즘 문제 풀기와 컴퓨터시스템 책에 대한 내용을 공부해야한다.


처음 본 팀원분들과 각자 컴퓨터시스템으로의 여행 1 챕터를 읽고 읽고 모르는 내용을 서로 공유하고 내용을 정리해 보겠다.
모든 정보는 비트의 연속이다
hello.c 프로그램처럼, 프로그래머가 작성한 소스 코드는 비트(0과 1)의 연속으로 저장
이 비트들은 8비트 단위인 바이트(byte)로 구성되며, 각 바이트는 하나의 문자를 나타냄
아스키(ASCII)를 통한 문자 표현
대부분의 시스템은 문자를 아스키 코드로 표현
이렇게 저장된 파일을 텍스트 파일이라 부르고, 아스키 문자가 아닌 데이터는 바이너리 파일이라 부름
컨텍스트(Context)의 중요성
동일한 비트/바이트라도 어떤 컨텍스트로 해석하느냐에 따라 의미가 완전히 달라짐
예: 같은 비트열이 문자, 정수, 실수, 기계어 명령 등으로 해석될 수 있음
즉, 비트 + 컨텍스트 = 의미 있는 정보
숫자 표현의 한계
컴퓨터의 숫자 표현(정수, 실수)은 유한한 비트로 근사된 값이기 때문에, 우리가 기대한 대로 동작하지 않을 수 있음

주석 제거
결과물: 전처리된 C 코드 → hello.i
컴파일 단계 (Compilation)
역할: C 코드를 어셈블리어로 번역
문법 검사, 변수 → 레지스터 할당, 조건문/루프 → 점프 등
결과물: 어셈블리 코드 → hello.s
어셈블리 단계 (Assembly)
역할: 어셈블리어를 기계어(목적 코드)로 변환
CPU가 직접 실행할 수 있는 이진 명령어로 구성
결과물: 목적 파일(Object file) → hello.o
링크 단계 (Linking)
역할: 여러 개의 목적 파일과 라이브러리 함수를 연결해 하나의 실행파일 생성
예: printf는 hello.c에 없고, 표준 라이브러리에 있음 → 링크 시 결합
결과물: 실행 가능한 바이너리 파일 → hello
프로그램 성능 최적화
컴파일러는 우수한 기계어 코드를 생성하지만, 프로그래머가 성능 최적화를 하려면 기계어 수준의 이해가 필요함.
링크 에러 이해
이런 질문을 이해해야 함:
"참조를 풀 수 없다"는 무슨 뜻?
정적 변수 vs 전역 변수?
동일한 이름의 전역 변수가 두 파일에 존재하면?
정적/동적 라이브러리 차이?
컴파일 시 라이브러리 순서가 왜 중요?
왜 링크 에러는 실행 전까지도 안 나올 수 있는가?
보안 약점 피하기
버퍼 오버플로우는 대표적인 보안 취약점
스택 구조와 메모리 저장 방식을 이해해야 보안에 강한 코드를 작성할 수 있음
이 취약점은 신뢰할 수 없는 데이터의 크기나 형식을 체크하지 않아서 생김
안전한 프로그래밍을 위해 어셈블리 수준의 이해도 중요

버스(Buses)
입출력 장치(I/O Devide)
메인 메모리(Main Memory)
프로세서(주처리장치, CPU)
레지스터(Register)
프로그램 카운터(PC, Program Counter)
수식/논리 처리기(ALU, Arithmetic logic unit)
CPU가 실행하는 단순한 작업 예

1. 쉘프로그램에 ./hello를 입력하면, 쉘 프로그램은 각각의 문자를 레지스터에 읽어들인 후 메모리에 저장

2. 키보드에서 엔터(Enter)를 누르면 쉘은 명령 입력을 끝난걸로 앎. 그러면 쉘은 파일 내의 코드와 데이터를 복사하는 일련의 인스트럭션을 실행하여 실행파일 hello를 디스크에서 메인 메모리로 로딩. 직접 메모리 접근기법(DMA)을 이용하여 데이터는 프로세서를 거치지 않고 디스크에서 메인 메모리로 직접 이동

3. hello의 목적파일의 코드와 데이터가 메모리에 적재된 후, 프로세서는 hello프로그램의 main 루틴의 기계어 인스트럭션을 실행하기 시작. 이 인스트럭션들은 hello, world\n를 메모리로부터 레지스터 파일로 복사하고, 거기로부터 디스플레이 장치로 전송하여 화면에 출력

저장장치 속도 계층(느림 → 빠름):
디스크 < 메모리 < 캐시 < 레지스터
예시:
문제: 프로세서 속도는 빨라지는데 메모리는 상대적으로 느림 → 속도 격차 발생
캐시의 핵심 원리: 지역성(Locality)
프로그램은 같은 데이터나 근처의 코드를 반복적으로 사용함
이 성질을 활용해 캐시에 저장해두면 CPU가 느린 메모리에 접근하는 빈도 줄일 수 있음
결론
응용 프로그래머가 캐시의 개념과 작동 원리를 이해하면,
프로그램 성능을 최대 10배 이상 개선할 수 있음
예시 구조
프로그래머의 역할
단순히 캐시뿐만 아니라 전체 메모리 계층 구조를 이해하면 데이터를 어디에 두고, 어떻게 접근할지 결정하여 성능을 크게 개선할 수 있음


운영체제(OS)는 하드웨어와 응용프로그램 사이의 중재자 역할을 함
응용프로그램은 하드웨어를 직접 제어하지 않고, 운영체제가 제공하는 서비스(시스템 콜 등)를 통해서만 하드웨어에 접근
운영체제의 2가지 주요 목적:
| 추상화 | 실제 하드웨어 |
|---|---|
| 프로세스 | CPU, 메모리, I/O 장치 |
| 가상 메모리 | 실제 메인 메모리 + 디스크 |
| 파일 | 디스크, I/O 장치 |
이 추상화를 통해 응용 프로그램은 하드웨어의 복잡성을 몰라도 되고, 더 안전하고 간편하게 실행될 수 있음
프로세스란?
실행 중인 프로그램에 대한 운영체제의 추상화
- hello 프로그램처럼, 실행 중인 모든 프로그램은 프로세스가 된다.
- 각각의 프로세스는 자신만 하드웨어를 쓰는 것처럼 보이도록 운영체제가 관리한다.
- 하지만 실제로는 한 CPU를 여러 프로세스가 교대로 사용한다 → 이것이 동시성(concurrency)

문맥 전환 (Context Switching)
컨텍스트 정보:
예시 시나리오: hello 프로그램 실행 과정
1. 쉘(shell) 프로그램이 입력 대기
2. 사용자가 ./hello 입력 → 쉘이 시스템 콜을 통해 운영체제에 제어권 넘김
3. 운영체제:
커널(kernel)이란?
요약 핵심 문장
쓰레드는 프로세스 내부에서 실행되는 하나의 흐름(제어 흐름)
개념
쓰레드의 장점
데이터 공유가 쉬움
효율성

가상메모리는 각 프로세스가 메모리를 독점적으로 사용하는 것처럼 보이게 만드는 환상
가상 메모리의 목적
여러 프로세스가 동시에 실행되어도 충돌하지 않도록 보호
각 프로세스에 독립적인 주소 공간 제공 (보안성, 안정성 확보)
가상 주소 공간 구성
1. 프로그램 코드와 전역 데이터
2. 힙(Heap)
3. 공유 라이브러리
4. 스택(Stack)
5. 커널 영역
작동 방식
파일은 연속된 바이트이며, 모든 입출력 장치는 파일로 모델링
디스크, 키보드, 디스플레이, 네트워크 등 모든 장치는 파일로 취급
유닉스 시스템에서 모든 입출력은 파일 읽기/쓰기와 같은 시스템 콜을 통해 이루어짐
장점
1. 장치에 대한 추상화
| 개념 | 정의 | 목적/장점 |
|---|---|---|
| 쓰레드 | 프로세스 내 실행 흐름 | 빠르고 가볍게 병렬 처리, 공유 메모리 활용 |
| 가상메모리 | 프로세스에 독립된 메모리 환상 제공 | 보호, 안정성, 효율적 메모리 사용 |
| 파일 | 연속된 바이트로 구성된 추상화 | 모든 장치 입출력 통일, 장치 독립성 제공 |
네트워크는 또 다른 입력장치로 볼 수 있음
시스템이 메인 메모리로부터 네트워크 어댑터로 일련의 바이트를 복사할 때, 데이터는 로컬디스크 드라이브 대신에 네트워크를 통해서 다른 컴퓨터로 이동
동시성 : 다수의 동시에 벌어지는 일을 갖는 시스템에 관한 일반적인 개념, 동시에 여러 작업이 진행 중인 것처럼 보임
병렬성 : 동시성을 사용해서 시스템을 보다 더 빠르게 동작하도록 하는 것, 여러 작업이 실제로 동시에 실행
쓰레드 수준 동시성