reference:
- "리눅스 커널 내부구조" / 백승재, 최종무
- "Operating Systems: Three Easy Pieces" / Remzi H. Arpaci-Dusseau and Andrea C. Arpaci-Dusseau
참조: 문자 디바이스 드라이버 추가 및 삭제 / https://temp123.tistory.com/16?category=877924
기본적으로 디바이스는 하드웨어를 의미하고, 드라이버는 그 디바이스를 제어하는 SW를 의미함.
예를 들어 UART 칩이 16개 달려있다고 했을 때 이를 제어하는 드라이버는 하나이고, 디바이스는 16개인 셈이다.
응용 프로그램이 디바이스를 직접 제어하는 것이 아니라 디바이스 드라이버를 통해 제어한다. 하지만 장치별로 제공하는 디바이스 드라이버가 다르다는 문제가 발생할 수 있다. 사용법이 회사마다 다르다면 응용 프로그래머 입장에선 부담이 크다.
다행히 리눅스 시스템에선 디바이스를 /dev 디렉터리에 하나의 파일로써 취급한다. 디바이스 드라이버도 마찬가지로 파일처럼 취급하는데, 이는 리눅스가 VFS(Virtual File System)을 제공하기 때문이다. /dev 디렉터리에 있는 디바이스 파일은 사용자가 접근할 수 있는 드라이버의 인터페이스 부분이다. 디바이스 드라이버가 파일로써 취급됨에 따라 open, close, read, write 등의 연산을 통해 접근할 수 있다.
추가로 디바이스 파일은 고유한 번호와 이름을 할당받는다. 이에 디바이스 드라이버를 제작하고 등록하기 위해서는 번호 및 이름을 지정해주어야 한다.
c: 캐릭터(문자) 디바이스
b: 블록 디바이스
n: 네트워크 디바이스
문자 디바이스 드라이버는 VFS에서 하나의 노드 형태로 존재한다. 이에 추후에 실습할 때 mknod 명령어를 통해 노드를 생성해주어야 한다.
자료의 순차성을 가지고 있는 하드웨어를 다룰 때 사용하며 데이터를 문자 단위(또는 연속적인 바이트 스트림)로 전달하고 읽어들인다. 대표적인 하드웨어로 터미널, 콘솔, 키보드, 사운드 카드, 스캐너, 프린터, 직렬/병렬 포트, 마우스, 조이스틱 등이 있다. (하드 드라이브나 플래시 메모리와 같은 저장장치는 포함되지 않는다.)
문자 디바이스 드라이버를 제작하고 등록하는 과정은 모듈 프로그래밍의 연장선으로 볼 수 있다.
기본적으로 모듈 프로그래밍 과정을 통해 디바이스 드라이버를 등록하기에 모듈 초기화 루틴(module_init) 매크로를 통해 virtual_device_init 함수(작성)를 구동하고, 이 함수 내에서 register_chrdev 함수를 통해 드라이버를 등록한다.
register_chrdev(250, "virtual_device", $vd_fops);
인수 1) 250: major number
인수 2) virtual_device: 등록할 디바이스 이름
인수 3) 디바이스 드라이버의 오퍼레이션들의 집합
static struct file_operations vd_fops = { .read = virtual_device_read, .write = virtual_device_write, .open = virtual_device_open, .release = virtual_device_release };
응용 프로그램에서 open, read, write, close와 같은 연산을 수행하면 커널의 시스템 콜을 호출하게 된다. 각각의 시스템 콜은 VFS에 등록된 연산을 호출하고, 이들은 맵핑된 디바이스 드라이버의 함수(virtual_device_read, virtual_device_write ..)들을 호출하는 매커니즘이다.