✅ [ v ] 멀티 프로세스 또는 스레드 이용한 장치 제어
pthread라이브러리를 사용하여 멀티 스레드 방식으로 서버를 구현함.- 클라이언트 요청 처리와 조도 센서 자동 감시 스레드를 분리하여 동시성 확보.
✅ [ v ] 대상 장치 제어 (LED / 부저 / 조도센서 / 7세그먼트)
- LED: PWM을 이용한 밝기 조절(최대/중간/최저) 및 On/Off 제어 (Active Low 회로 대응).
- 부저 : 멜로디 연주 및 경고 비프음 출력.
- 조도센서 : 실시간 값 확인 및 자동 제어(Auto Mode) 연동.
- 7세그먼트 : 타이머 카운트다운 기능 구현.
✅ [ v ] 공유 라이브러리(Shared Library) 형식 작성
- 하드웨어 제어 코드를
mydevices.c로 분리하고libmydevices.so동적 라이브러리로 빌드함.- 서버 재컴파일 없이 라이브러리 교체만으로 장치 기능 업그레이드가 가능한 구조.
✅ [ v ] 클라이언트 시그널 처리
signal(SIGINT, handler)를 등록하여Ctrl+C입력 시 소켓을 닫고 안전하게 종료되도록 처리함.
✅ [ v ] 서버 데몬(Daemon) 프로세스 구성
fork(),setsid()등을 사용하여 터미널 종료 후에도 백그라운드에서 실행되는 데몬 프로세스로 구현.
✅ [ v ] 빌드 자동화 (Make 이용)
Makefile을 작성하여 라이브러리 링크 및 서버/클라이언트 빌드를 자동화함.
project_submit/ ├── code/ │ ├── client/ # 클라이언트 소스코드 (client.c) │ ├── server/ # 서버 및 라이브러리 소스코드 (server.c, mydevices.c, mydevices.h) │ └── Makefile # 빌드 자동화 스크립트 ├── exec/ │ ├── lib/ # 공유 라이브러리 (.so) 저장소 │ ├── server # 서버 실행 파일 │ └── client # 클라이언트 실행 파일 ├── docs/ # 개발 문서 (Manual, README) └── misc/ # 회로도 및 기타 자료
리눅스 콘솔부터 디바이스 드라이버까지의 흐름은 "사용자 영역(User Space)에서 커널 영역(Kernel Space)을 거쳐 하드웨어(Hardware)를 제어하는 과정"을 이해하는 것이 핵심입니다.

: 리눅스에서 콘솔은 단순한 입출력 창이 아니라, 커널과 상호작용하는 중요한 인터페이스 장치입니다.
물리적 콘솔: 모니터와 키보드가 직접 연결된 터미널 (/dev/tty1 ~ tty6). Ctrl+Alt+F1 등으로 접근합니다.
시리얼 콘솔 (UART): 임베디드 보드 디버깅 시 가장 많이 사용합니다 (/dev/ttyS0, /dev/ttyAMA0 등). 네트워크가 끊겨도 하드웨어적으로 접근 가능한 비상구 역할을 합니다.
가상 터미널 (PTS/PTY): SSH 접속이나 GUI 터미널 창(gnome-terminal 등)을 사용할 때 생성되는 가상 장치입니다.
: 리눅스는 "모든 것을 파일로 취급"합니다. 따라서 콘솔 화면에 글자를 띄우는 것도 사실은 특정 장치 파일에 데이터를
write()하는 과정입니다.

: 애플리케이션(유저 영역)이 하드웨어를 직접 제어할 수 없기 때문에, 커널에게 요청을 보내는 과정입니다.
: 유저 프로그램이 커널의 기능을 호출하는 통로입니다.
open(), read(), write(), close(): 기본적인 파일 입출력.ioctl() (Input/Output Control): 디바이스 드라이버에서 매우 중요합니다. 단순히 데이터를 읽고 쓰는 것을 넘어, 하드웨어의 특정 설정(예: 통신 속도 변경, LED 깜빡임 모드 설정 등)을 제어할 때 사용합니다.: 리눅스는 디바이스 드라이버도 파일처럼 다루게 해줍니다. 응용 프로그램은 그 뒤에 있는 것이 실제 파일인지, 하드웨어 센서인지 알 필요 없이 똑같은 함수(read/write)를 사용합니다.

: 디바이스 드라이버는 "특정 하드웨어를 제어하는 커널 내부의 함수 집합"입니다.
(1) 문자 디바이스 (Character Device):
특징: 데이터를 스트림(Byte 단위)으로 순차적으로 처리합니다. 버퍼 캐시를 사용하지 않습니다.
예시: 키보드, 마우스, 시리얼 포트, GPIO 센서, LED 등.
학습 포인트: 임베디드 입문 시 가장 먼저, 그리고 많이 다루게 될 영역입니다.
(2) 블록 디바이스 (Block Device):
특징: 데이터를 블록 단위(보통 512B, 4KB)로 처리하며 랜덤 액세스가 가능합니다.
예시: 하드디스크, SSD, SD 카드.
(3) 네트워크 디바이스 (Network Device):
특징: 파일 시스템 노드가 없으며, 소켓 인터페이스를 통해 접근합니다.
예시: 이더넷 카드, Wi-Fi 모듈.
모듈 (Module, .ko)
: 커널을 다시 컴파일하지 않고도 실행 중에 드라이버를 로드(insmod)하거나 제거(rmmod)할 수 있는 형태입니다.
주번호(Major)와 부번호(Minor):
- Major Number: 드라이버의 종류를 식별 (예: "이것은 LED 드라이버다").
- Minor Number: 같은 드라이버 내에서 하드웨어 구분 (예: "LED 1번", "LED 2번").
File Operations (struct file_operations): 가장 중요한 구조체입니다. 유저 공간의 open, read, write 시스템 콜이 호출되었을 때, 실제 커널 드라이버 내에서 어떤 함수가 실행될지 연결(Mapping)해줍니다.
디바이스 트리 (Device Tree, DTS): (특히 ARM 리눅스에서 중요) 하드웨어의 정보(물리 주소, 인터럽트 번호 등)를 커널 코드에 하드코딩하지 않고, 별도의 텍스트 파일로 기술하여 커널에 전달하는 방식입니다.
사용자가 LED를 켜는 프로그램을 실행했을 때의 흐름은 다음과 같습니다.
(1) User App:
open("/dev/led", O_WRONLY)호출 ->write(fd, "1", 1)호출.(2) System Call Interface: 유저의 요청을 받아 커널 모드로 전환.
(3) VFS:
/dev/led가 연결된 Major Number를 확인하고 해당 드라이버를 찾음.(4) Device Driver:
file_operations에 등록된led_write()함수 실행.(5) Kernel API:
led_write()내부에서iowrite32()등을 통해 실제 하드웨어 레지스터 값을 변경.(6) Hardware: CPU 핀의 전압이 High로 바뀌며 LED 점등.
lsmod: 현재 로드된 커널 모듈 확인.
insmod / rmmod: 모듈 적재 및 제거.
dmesg: (가장 중요) 커널 로그 버퍼를 출력합니다. 드라이버의 printk() 출력 내용을 여기서 확인하며 디버깅합니다.
strace: 프로그램이 호출하는 시스템 콜을 추적합니다. (예: strace ./my_app)
/proc & /sys: 커널의 상태 정보나 디바이스 정보를 파일 형태로 조회할 수 있는 가상 파일 시스템입니다.