지난 게시글에서는 C 코드에서 시스템 콜을 사용해 컴파일하고 실행함으로써 실제 하드웨어 핀에 접근했는데, 그렇다면 시스템 콜(system call)이란 정확히 무엇일까?
이를 이해하기 위해서는 OS(Linux)를 사용하는 경우와 RTOS, 그리고 Bare-Metal(FPGA에 직접 HW 로직을 구현 후, 레지스터 레벨로 접근)의 명확한 차이를 알아야만 한다.
사실 이를 한 문장으로 정리하자면 다음과 같다.
1. 베어메탈 (Bare-metal)
▷ 개념
운영체제 없이 main() 함수 안에서 직접 MCU/SoC의 레지스터를 제어하는 방식
하드웨어 위에 소프트웨어가 얇게 올라간 구조로, Start-up Code + Application Code로만 구성됨.
▷ 용도
간단한 센서 제어, LED 제어, FPGA 초기화 코드
자원 제약이 심한 MCU (예: STM32, ATmega 등)
▷ 장점
낮은 오버헤드: OS 커널이 없어 실행 속도 빠름
정확한 타이밍 제어: 딜레이 루프, 인터럽트 등을 직접 컨트롤
메모리 사용 최소화: RAM, ROM 적게 사용
▷ 단점
멀티태스킹 어려움
복잡한 프로그램 구성 시 코드 유지보수 어려움
타이밍 충돌, 우선순위 문제 수동 처리 필요
2. RTOS (Real-Time Operating System)
▷ 개념
실시간 동작이 중요한 시스템을 위해 설계된 OS로, 작업 우선순위 기반 스케줄링, 태스크 분리, 인터럽트 처리 등을 지원함. (FreeRTOS, Zephyr, RTX)
▷ 용도
드론 제어, 차량 제어, 산업용 제어기, 로봇 제어 시스템
수 밀리초 ~ 수십 밀리초 단위의 빠른 반응이 필요한 상황
▷ 장점
실시간성 보장 (Hard/Soft real-time)
멀티태스킹 가능: Task, Semaphore, Mutex로 안정적 분산 처리
중소형 시스템에 최적: 커널 크기가 작고 설정 유연
▷ 단점
RTOS마다 제공 API, 스케줄링 정책 다름 (이식성 부족)
디버깅 어려움: Race condition, Deadlock 발생 가능
일반 OS처럼 복잡한 파일 시스템, 네트워크는 제한적
3. OS (Linux 등)
▷ 개념
일반적으로 사용하는 범용 OS로, 가상 메모리, 파일 시스템, 드라이버, 사용자 관리, 프로세스 관리 등 다양한 기능 포함
▷ 용도
임베디드 리눅스 기반 디바이스 (예: Zynq, Raspberry Pi)
멀티미디어 처리, 네트워크 통신, 복잡한 앱 필요 시
▷ 장점
풍부한 기능 & 오픈소스 생태계 활용 가능
파일 시스템, TCP/IP, USB, Camera 등 복합 서비스 지원
다중 사용자, 프로세스 환경에 강함
드라이버와 커널 모듈을 통해 하드웨어 추상화
▷ 단점
시스템 부팅 느림, 메모리 사용 많음
정확한 타이밍 제어 어려움
설정/이식/디버깅 복잡
그렇다면 위에 대한 이해를 바탕으로 시스템 콜이 무엇인지 이해해보자.
위에서 말했듯이 운영체제(OS)는 다양한 애플리케이션이 동시에 동작하는 복잡한 환경을 가정한다. 이때, 모든 애플리케이션이 하드웨어를 직접 제어할 수 있게 허용한다면, 시스템은 금방 무너지게 될 것이다.
이를 방지하기 위해 OS는 이렇게 구성된다.
- 유저 공간은 프로그램들을 실행하는 안전한 공간
- 커널 공간은 자원을 통제하고, 하드웨어를 직접 제어하는 공간
- 시스템 콜(System Call)은 유저 공간에서 커널 기능을 요청하는 공식적인 통로
- 시스템 콜은 유저 공간 애플리케이션이 커널에 요청을 보내는 함수라고 생각하면 된다.
- 즉, "나 이 UART를 쓰고 싶어요", "이 파일을 읽고 싶어요", "이 메모리 좀 주세요" 같은 요청을
커널에게 전달하고, 커널이 대신 처리해주는 구조이다.
User Program (C 코드에서 시스템 콜 호출 (open(), write(), read(), ioctl() 등))
↓
System Call Interface
↓
Kernel (OS 내부)
↓
Device Driver / Scheduler / Memory Manager
↓
Hardware (UART, RAM, Timer 등)
그래서 사실 우리가 쉘에서 흔히 사용하는 ls, mkdir, rm, cat, echo 등은 단순한 키워드가 아니라, C 언어로 작성된 실행파일이다. 이 프로그램들은 내부적으로 시스템 콜(openat(), getdents(), fstatat() 등)을 호출하여 커널을 통해 하드웨어 자원을 제어한다.
진짜인지 확인해보고 싶다면, 해당 명령어들은 모두 GNU coreutils라는 오픈소스 프로젝트에 포함되어 있으며, 아래 경로에서 C 소스코드를 직접 확인할 수 있다.
GitHub - coreutils/coreutils: upstream mirror
upstream mirror. Contribute to coreutils/coreutils development by creating an account on GitHub.
github.com
'Linux > Embedded Linux (Rpi)' 카테고리의 다른 글
리눅스 시스템 구조와 부트 과정 이해(5) - 디바이스 트리 (0) | 2025.05.04 |
---|---|
리눅스 시스템 구조와 부트 과정 이해(4) - Bootloader (0) | 2025.05.03 |
리눅스 시스템 구조와 부트 과정 이해(2) - 임베디드 리눅스에서의 UART (0) | 2025.05.03 |
리눅스 시스템 구조와 부트 과정 이해(1) - dmesg, 부트로더 (0) | 2025.04.20 |
Embedded Linux를 공부하는 이유 (0) | 2025.04.18 |