![[Embedded] 시스템 프로그래밍 개요 : 리눅스 시스템 프로그래밍의 이해](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdna%2FF2YiU%2FbtsNAHrXFNE%2FAAAAAAAAAAAAAAAAAAAAAPOxV3tPMTcW2sEoJHf_t1WOjocImuJKtFGu6iJK-ZrR%2Fimg.png%3Fcredential%3DyqXZFxpELC7KVnFOS48ylbz2pIh7yKj8%26expires%3D1753973999%26allow_ip%3D%26allow_referer%3D%26signature%3DpyTmNDecz1njafa%252FMPGCw38oxWg%253D)
시스템 (System)
시스템 (System)
- 정의 : 어려 구성 요소(하드웨어, 소프트웨어, 사람, 절차 등)가 상호작용하여 하나의 목표를 달성하도록 조직된 집합 (구성요소들이 상호작용하는 집합체 = 시스템)
- 공통 속성
- 입력 (Input) ➡️ 처리 (Processing) ➡️ 출력 (Output) ➡️ 피드백 (Feedback)
- 경계 (Boundary) : 시스템을 외부 환경과 구분하는 경계가 존재
컴퓨팅 시스템 (Computing System)
컴퓨팅 시스템의 목적
- 범용적인 연산, 저장, 통신 기능을 제공해 다양한 응용 프로그램을 실행
컴퓨팅 시스템의 구성
- 하드웨어 : CPU, 메모리, 저장장치, I/O 장치, 네트워크 어댑터 등
- 시스템 소프트웨어 : BIOS/UEFI ➡️ OS ➡️ Drvier · Runtime
- 응용 소프트웨어 : 브라우저, IDE, 게임, 데이터베이스 등
컴퓨팅 시스템의 특징
- 범용성 : 필요에 따라 어떤 소프트웨어든 설치 및 교체 가능
- 확장성 : 하드웨어 업그레이드가 비교적 용이
- 사용자 인터페이스 : 키보드, 마우스, 모니터 등과 같은 풍부한 입출력 장치
- 성능 지향 : 고클럭 CPU, 멀티코어, 대용량 메모리 및 스토리지 활용
임베디드 시스템 (Embedded System)
임베디드 시스템의 목적
- 어떤 제품 및 장치 내부에 내장되어 특정 기능(제어, 계측, 통신 등)을 수행
임베디드 시스템의 구성
- 마이크로컨트롤러(MCU) / SoC : CPU + 메모리 + 주변장치가 하나의 칩에 통합
- 펌웨어 / RTOS : Bare-metal 코드, FreeRTOS, Zephyr, VxWorks 등
- 센서 및 액추에이터 : 온도 센서, 모터, 디스플레이, RF 모듈 등
- 전원 관리 : 베터리, 전력 변환 회로, 저전력 슬립 모드
임베디드 시스템의 특징
- 전용성 : 출하 후 기능 변화가 제한적(OTA 업데이트 지원 시 일부 기능 추가 가능)
- 제약 조건 : CPU 클럭수, 전력 및 공간 제한 등
- 실시간성 : 하드웨어 및 소프트웨어 실시간 제어 (마이크로 ~ 밀리 초 내에 인터럽트 처리)
- 신뢰 및 안전 : 자동차, 의료기기, 항공우주처럼 실패 허용도가 매우 낮음
컴퓨팅 시스템 vs 임베디드 시스템
- 컴퓨팅 시스템은 범용, 대규모, 사용자 중심의 시스템
- 임베디드 시스템은 전용, 제약 지향, 실시간 중심의 시스템
구분 | 컴퓨팅 시스템 | 임베디드 시스템 |
주요 목적 | 범용 계산, 다중 응용 실행 | 제품 기능 전용 제어 및 계측 |
사용자 인터페이스 | 그래픽 UI, 다수 입출력 장치 | 보이지 않거나 단순 버튼 및 LED |
하드웨어 규모 | 데스크톱, 서버, 노트북 | MCU, 단판 컴퓨터(ex. 라즈베리파이) |
성능 및 자원 | 고성능 CPU/GPU, GB~TB 메모리 및 스토리지 | 저전력 코어, KB ~ MB 메모리 및 Flash |
운영체제 | 완전형 OS (ex. Linux, Windows 등) | RTOS, 임베디드 Linux, Bare-metal |
유연성 및 업그레이드 | 하드웨어 및 소프트웨어 모두 교체 용이 | 설계 및 출하 단계에서 기능 고정이 많음 |
실시간 요구 | 대체로 Soft RT 또는 None | Hard/Soft RT, 마이크로 ~ 밀리 초 단위 응답 |
전력 및 공간 제약 | 전력 풍부, 냉각 장치 사용 | 베터리 구동, 팬리스 및 초소형 폼팩터 |
개발 툴체인 | GCC/Clang, JIT, 가상화 플랫폼 | 크로스컴파일러, J-TAG, In-Circuit Debugger |
예시 | 서버 팜, 개인용 PC, 클라우드 VM | 스마트워치, ABS 제어기, 드론 FC, 가전제품 |
시스템 프로그래밍 개요
System Programming
- 시스템 프로그래밍(System Programming)은 운영체제와 하드웨어 자원을 직접 제어하거나, 운영체제가 제공하는 인터페이스(시스템 콜, API 등)를 통해 자원을 관리하고 최적화하는 프로그래밍을 통칭
시스템 프로그래밍의 대상 영역 (Scope)
시스템 프로그래밍이 이루어지는 영역은 하드웨어 제약을 직접 다루고, 커널 인터페이스나 레지스터 수준까지 내려와 성능, 메모리 및 안전성을 최우선으로 고려하여 프로그래밍한다는 공통점이 존재
커널 및 OS 개발
프로세스, 메모리, 파일 시스템 및 드라이버를 모두 아우르는 핵심 소프트웨어(커널)와 그 주변 서비스(부트, 시그널, 시스템 콜)를 설계 및 구현하는 분야
- 예시 : Linux | Windows NT | RTOS
- 필수 개념 : 프로세스 스케줄링 | 메모리 관리자 | 파일 시스템 | 드라이버 프레임워크
드라이버 & 펌웨어
하드웨어 레지스터와 직접 대화하며 장치를 초기화 및 제어하는 코드(펌웨어, 커널/유저 드라이버)를 작성하는 분야
드라이버는 OS가 하드웨어를 추상화하여 응용 프로그램이 사용할 수 있도록 지원하며, 펌웨어는 하드웨어의 기본 동작을 정의하고 OS와 독립적으로 실행 가능
- 예시 : 그래픽 드라이버 | 네트워크 드라이버 | UEFI | MCU 펌웨어
- 필수 개념 : 인터럽트 | DMA | 레지스터 맵 | 하드웨어 프로토콜
런타임 · 라이브러리
언어 런타임(libc, GC, 쓰레드 런타임 등)과 공용 시스템 라이브러리를 구현 및 최적화하여 응용 프로그램이 OS 기능을 쉽게 쓸 수 있도록 다리 역할을 하는 분야
- 예시 : libc | libstdc++ | musl | OpenSSL
- 필수 개념 : ABI | 시스템 호출 래퍼 | 메모리 및 스레드 안전성
시스템 유틸리티 및 툴 체인
"사용자 눈앞의 시스템 명령" 또는 컴파일러, 링커, 디버거 등 개발 도구를 제작 및 보수하는 분야
- 예시 : Shell | coreutils (GNU 코어 유틸리티) | 시스템 모니터
- 필수 개념 : 파일 및 프로세스 제어 | 터미널 I/O | 성능 최적화
가상화 · 컨테이너
하이퍼바이저(KVM), 애뮬레이터(QEMU)를 통해 완전한 논리적 OS 인스턴스(가상 머신)를 실행하거나, 네임스페이스, cgroup을 활용해 호스트 OS 커널을 공유하는 격리된 실행 환경(컨테이너)을 제공하는 분야
- 예시 : KVM | QEMU | Docker runc
- 필수 개념 : 하이퍼바이저 | 네임스페이스 | cgroup
네트워크 스택
프로토콜 구현부터 패킷 라우팅 및 필터링까지, 커널과 유저 공간을 넘나들며 데이터가 안전하고 빠르게 전송될 수 있도록 구축하는 분야
- 예시 : TCP/IP 구현 | eBPF/XDP
- 필수 개념 : 소켓 | 패킷 파싱 | eBPF/XDP를 통한 커널-유저 공간 상호작용
고성능 · 병렬 시스템
캐시 · NUMA · SIMD · 락 프리 구조를 활용해 데이터베이스, 게임 엔진, 분산 시스템 등 "마이크로초 단위 지연"에 민감한 소프트웨어의 내부 코어를 다루는 분야
- 예시 : 데이터베이스 엔진 | 게임 엔진 코어
- 필수 개념 : 캐시 최적화 | NUMA | SIMD | lock-free 알고리즘
임베디드 · IoT
제한된 자원 위에서 실시간 제어와 저전력 동작을 보장하도록 보드 지원 패키지(BSP), RTOS 앱, 디바이스 드라이버를 개발하는 영역
- 예시 : 라즈베리파이 BSP | RTEMS | FreeRTOS 앱
- 필수 개념 : 핀/버스 제어 | 저전력 | 크로스컴파일
시스템 프로그래밍의 특성
- 낮은 추상화 레벨
- 고급 언어 추상화를 우회하고, 구조체 한 바이트 차이 및 메모리 얼라인먼트까지 신경써야 함
- 직접적인 자원 관리
- 동적 메모리, 파일 디스크립터, 쓰레드·락을 직접 열고 닫으며 누수가 없도록 책임져야 함
- 하드웨어 및 OS 의존성
- x86 vs ARM, Windows vs POSIX 등 환경마다 API, 메모리 모델이 달라 휴대성이 제한됨
- 성능 및 지연에 민감
- 수십 나노초의 컨텍스트 스위치나 캐시 미스가 병목인지 판단하고 최적화함
- 안정성과 보안
- 커널 패닉 및 시스템 크래시 가능성을 항상 염두해 두고, 권한 상승과 메모리 오염을 막아야 함
자주 사용되는 언어 및 툴체인
자주 사용되는 언어
- C
- 사용 이유 : 얇은 런타임, 포인터 및 비트 조작, POSIX API
- 대표 사용처 : 리눅스 커널 및 드라이버, libc
- C++
- 사용 이유 : OOP + RAII + 템플릿 및 STL(표준라이브러리) 사용 가능
- 대표 사용처 : 게임 엔진, 네이티브 DB, 브라우저
- Rust
- 사용 이유 : 메모리 안전성, 제로비용 추상화
- 대표 사용처 : 드라이버 및 네트워크 스택(XDP), 커널 모듈
- 어셈블리
- 사용 이유 : 인라인 최적화, 부트로더
- 대표 사용처 : 펌웨어, SIMD 핵심 루틴
- Go
- 사용 이유 : 간결한 동시성 모델(goroutine), 강력한 표준 라이브러리, 네트워크 및 분산 시스템에 적합
- 대표 사용처 : Docker, Kubernetes, Caddy (웹 서버), 시스템 유틸리티
- Python (보조)
- 사용 이유 : 빌드 스템, 테스팅, 자동화
- 대표 사용처 : 빌드 스크립트, 시스템 테스트
자주 사용되는 툴체인
- GCC / Clang (크로스 컴파일 포함, ex.
arm-none-eabi-gcc
) - binutils
- gdb
- strace
- perf
- Valgrind
- QEMU
- Wireshark
- Make, CMake, Ninja (빌드 시스템)
리눅스 시스템 프로그래밍
- 리눅스 시스템 프로그래밍(Linux System Programming)은 리눅스 운영체제에서 제공하는 시스템 호출과 POSIX 표준 라이브러리 함수를 사용하여 응용 프로그램과 운영체제 커널 사이의 인터페이스를 다루는 프로그래밍 영역을 의미
- 운영체제의 기능(파일 입출력, 프로세스 관리, 메모리 관리, 쓰레드 관리, IPC 등)을 시스템 호출 또는 사용자 공간 라이브러리를 통해 직접적으로 활용하여 프로그래밍하는 것으로, 커널이 제공하는 API를 통해 하드웨어 자원에 접근하고 관리하는 프로그래밍
- 주로 시스템 호출, 파일 입출력 및 파일 시스템 관리, 프로세스 관리, 메모리 관리, 쓰레드 관리, 프로세스 간 통신, 그리고 네트워크 프로그래밍으로 이루어져 있음
시스템 호출 (System Call)
- 사용자 프로그램이 커널에 요청을 보내고, 필요한 자원을 할당받거나 하드웨어를 제어하는 데 사용
- 줄여서 시스콜(Syscall)이라고도 함
- 주요 예시
- 파일 I/O :
open()
,close()
,read()
,write()
- 프로세스 관리 :
fork()
,exec()
,wait()
,exit()
- 메모리 관리 :
brk()
,mmap()
- IPC :
pipe()
,msgget()
,shmget()
,semget()
- 네트워크 관리 :
socket()
,connect()
,bind()
,listen()
- 파일 I/O :
파일 입출력 및 파일 시스템 관리
- 파일은 리눅스에서 입출력의 기본 단위이자, 파일 시스템을 관리하는 단위
- 주요 시스템 콜
- 파일 열기 및 닫기 :
open()
,close()
- 데이터 입출력 :
read()
,write()
- 파일 포인터 관리 :
lseek()
- 메타데이터 관리 :
stat()
,chmod()
,chown()
- 파일 열기 및 닫기 :
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main() {
int fd = open("example.txt", O_CREAT | O_WRONLY, 0644);
if(fd < 0) {
perror("open");
return -1;
}
write(fd, "Hello, Linux System Programming!\n", 33);
close(fd);
return 0;
}
프로세스 관리 (Process Management)
- 프로세스 생성, 종료, 실행 등의 기능을 다룸
- 주요 시스템 콜
- 프로세스 생성 :
fork()
- 프로세스 종료 :
exit()
,kill()
- 프로세시 실행 :
exec()
계열의 함수 - 프로세스 상태 관리 :
wait()
- 프로세스 생성 :
#include <stdio.h>
#include <unistd.h>
int main() {
pid_t pid = fork();
if (pid == 0) { // Child
printf("Child process, PID: %d\n", getpid());
} else if (pid > 0) { // Parent
printf("Parent process, PID: %d\n", getpid());
wait(NULL);
} else {
perror("fork");
return -1;
}
return 0;
}
메모리 관리 (Memory Management)
- 리눅스의 메모리 관리 API를 통해 메모리를 동적으로 할당 및 해제
- 주요 시스템 콜
- 메모리 매핑 :
mmap()
,munmap()
- 힙 메모리 관리 :
malloc()
,free()
(glibc
를 통해mmap()
또는sbrk()
사용)
- 메모리 매핑 :
#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
int main() {
size_t pagesize = getpagesize();
void *ptr = mmap(NULL, pagesize, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
if(ptr == MAP_FAILED) {
perror("mmap");
return -1;
}
sprintf(ptr, "Linux Memory Management");
printf("%s\n", (char*)ptr);
munmap(ptr, pagesize);
return 0;
}
쓰레드(Thread) 관리
- 멀티쓰레드 프로그래밍을 지원
- 리눅스에서는 POSIX 쓰레드 사용
- 주요 함수
- 쓰레드 생성 및 종료 :
pthread_create()
,pthread_join()
,pthread_exit()
- 동기화 : Mutex, Semaphore, Condition Variables
- 쓰레드 생성 및 종료 :
#include <pthread.h>
#include <stdio.h>
void* worker(void* arg) {
printf("Thread says: %s\n", (char*)arg);
return NULL;
}
int main() {
pthread_t tid;
pthread_create(&tid, NULL, worker, "Hello, Thread!");
pthread_join(tid, NULL);
return 0;
}
프로세스 간 통신 (Inter Process Communication, IPC)
- 프로세스끼리 데이터를 교환하고 통신하기 위한 메커니즘을 제공
- 주요 방식
- 파이프 (pipe)
- 메세지 큐 (message queue)
- 공유 메모리 (shared memory)
- 세마포어 (semaphore)
- 소켓 (socket)
#include <unistd.h>
#include <stdio.h>
int main() {
int fd[2];
pipe(fd);
pid_t pid = fork();
if (pid == 0) { // Child
close(fd[0]);
write(fd[1], "IPC via pipe", 13);
close(fd[1]);
} else { // Parent
char buf[20];
close(fd[1]);
read(fd[0], buf, 20);
printf("Received: %s\n", buf);
close(fd[0]);
}
return 0;
}
네트워크 프로그래밍
- 소켓 API를 통해 네트워크 프로그래밍을 지원
- 주요 시스템 콜
- 소켓 생성 및 연결 :
socket()
,bind()
,listen()
,accept()
,connect()
- 데이터 송수신 :
send()
,recv()
- 소켓 생성 및 연결 :
'🖥️ Dev > Embedded' 카테고리의 다른 글
[임베디드] LwM2M 프로토콜의 개념과 이해 (1) | 2025.06.30 |
---|---|
[Embedded] 시스템 프로그래밍 개요 : 시스템 프로그래밍에 대한 전반적 이해 (0) | 2025.04.27 |
[Embedded] 시스템 프로그래밍 개요 : 시스템에 대한 전반적 이해 (0) | 2025.04.27 |
since 2025.01.27. ~ 개발자를 향해....🔥