컴퓨터 시스템 - week1

낚시하는 곰·2025년 3월 14일

krafton jungle

목록 보기
12/52

0과 1로 모든 문자를 표현할 수 있다.

ASCII (미국 표준 코드, 7비트)

'A' → 65 → 01000001 (2진수)
'B' → 66 → 01000010
'a' → 97 → 01100001
'1' → 49 → 00110001

문자는 총 8비트로 구성되어 있다.

'H' → 72 → 01001000
'i' → 105 → 01101001

문자를 2진수로 변환


바이너리 파일이 링킹되는 과정

[ hello.c ]   [ printf.c ]   
    │             │      
    ▼             ▼      
  hello.o       printf.o  (컴파일)
    │             │      
    ▼             ▼      
   [ Linker 결합 ]        
        │                 
        ▼                 
    실행 파일 생성 (hello)  

링킹이란

컴파일러가 생성한 오브젝트 파일(.o)을 하나로 결합하여 실행 파일을 만드는 과정

결합하는 과정이 필요한 이유는 만약 컴파일 과정에서 외부 라이브러리를 사용했다면 사용한 라이브러리와 이어주는 역할을 해주는 링커가 있어야 함.

링킹이 필요한 이유

// math.c (math.o로 컴파일)
int add(int a, int b) {
    return a + b;
}
// main.c (main.o로 컴파일)
#include <stdio.h>

int add(int a, int b); // math.o에 있는 함수 선언

int main() {
    printf("3 + 5 = %d\n", add(3, 5));
    return 0;
}
gcc -c math.c -o math.o
gcc -c main.c -o main.o
gcc main.o math.o -o program  # 링킹

위를 살펴보면 외부에 math.c를 생성하고 main.c에서 math에 있는 add 함수를 호출하고 있다. 이러면 main에서는 math와 연결해주는 뭔가가 있어야 한다.

링커의 역할

(1) 심볼 해석(Symbol Resolution)
main() 함수가 호출하는 printf() 같은 함수의 실제 위치를 찾아서 연결

(2) 주소 재배치(Relocation)
printf() 같은 함수가 실행될 때, 실행 가능한 메모리 주소를 설정

(3) 실행 파일 생성(Executable Generation)
모든 .o 파일과 라이브러리를 결합하여 실행 파일을 만듦

CLI의 동작 원리

[ 1. 사용자가 명령어 입력 ]
        │
        ▼
[ 2. 쉘이 명령어 해석 (파싱) ]
        │
        ▼
[ 3. 쉘 내장 명령어인지 확인 ]
        │
        ├── 쉘 내장 명령어면 직접 실행 (cd, exit 등)
        │
        └── 외부 명령어면 실행 파일 찾기 (ls, grep 등)
        │
        ▼
[ 4. 실행 파일을 찾으면 프로세스 생성 (fork) ]
        │
        ▼
[ 5. 새로운 프로세스에서 프로그램 실행 (execve) ]
        │
        ▼
[ 6. 명령어 실행 후 쉘이 결과 출력 ]
        │
        ▼
[ 7. 쉘이 다음 명령어 입력 대기 ]

전형적인 하드웨어 구성

     +----------------------------------------------------+
     |                     CPU (중앙처리장치)             |
     |  +-------------------+   +-------------------+    |
     |  | 연산장치 (ALU)     |   | 제어장치 (CU)     |    |
     |  +-------------------+   +-------------------+    |
     |                  | 레지스터 (Registers)           |
     +----------------------------------------------------+
                              │
                              ▼
     +----------------------------------------------------+
     |                    시스템 버스 (System Bus)        |
     |  +----------+    +---------+    +----------------+ |
     |  | 주소 버스 |    | 데이터 버스 |    | 제어 버스 |  |
     |  +----------+    +---------+    +----------------+ |
     +----------------------------------------------------+
          │                     │                      │
          ▼                     ▼                      ▼
+-----------------+     +----------------+      +--------------------+
|  메인 메모리   |     | 입출력 장치    |      | 보조 기억 장치      |
| (RAM, 캐시)    |     | (키보드, 마우스)|      | (HDD, SSD)         |
+-----------------+     | (모니터, 프린터)|      +--------------------+
                        +----------------+

시스템 버스 이해하기

CPU → 주소 버스 → [메모리 주소 0x1000] 요청
CPU → 제어 버스 → "READ" 신호 전송

cpu에서 메모리로 0x1000주소에 저장되어 있는 데이터의 '읽기'모드로 요청.

메모리 → 데이터 버스 → [데이터 0xFF] 전송
메모리 → 제어 버스 → "응답 완료" 신호 전송

메모리에서 데이터를 cpu로 전송하고 '응답 완료' 신호를 보냄.

CPU → 레지스터에 0xFF 저장 → 명령어 실행

cpu는 받은 데이터를 레지스터 0xFF주소에 저장하고 명령어를 실행합니다.

멀티 태스킹 이해하기

(1) Chrome 실행 → RAM에 로드
(2) VS Code 실행 → RAM에 로드
(3) 음악 플레이어 실행 → RAM에 로드
(4) CPU가 프로그램을 번갈아가며 실행 (컨텍스트 스위칭)

RAM에 여러 개의 프로그램을 올려두고, CPU가 빠르게 전환하면서 실행함.

프로그램 실행 과정

1️⃣ 사용자가 실행 파일(hello.exe) 클릭
2️⃣ 운영체제가 실행 파일을 RAM으로 복사 (로드)
3️⃣ CPU가 RAM에서 명령어를 읽고 실행
4️⃣ 실행이 끝나면 프로그램이 RAM에서 제거됨

C프로그램이 실행되는 과정

#include <stdio.h>
int main() {
    printf("Hello, World!\n");
    return 0;
}
1️⃣ 실행 파일 a.out (HDD/SSD에 저장됨)
2️⃣ 실행 요청 시 a.out이 RAM으로 복사됨 (로드)
3️⃣ CPU가 RAM에서 한 줄씩 명령어를 읽어 실행 (Fetch-Decode-Execute)
4️⃣ 실행이 끝나면 프로그램이 메모리에서 제거됨
profile
취업 준비생 낚곰입니다!! 반갑습니다!!

0개의 댓글