임베디드 스터디 - 디바이스 드라이버 기본
임베디드 스터디 - 디바이스 드라이버 기본
커널 공간 / 사용자 공간
- 운영체제는 사용자 프로그램이 하드웨어에 직접 접근하는 걸 허용하지 않음
- 이유는 두 가지임
- 안전성 : 레이스 컨디션, 데이터 오염, 시스템 마비 방지
- 보안성 : 악의적 프로세스의 하드웨어 탈취 방지
- CPU의 Privilege Mode는 사용자 공간에서 MMIO에 직접 접근하려 할 때 즉시 Exception을 발생시킴
Everything is a File
- Linux 시스템의 기본 철학 : 모든 자원을 파일 인터페이스로 통일함
- 일반 파일뿐 아니라 하드웨어 장치, 프로세스 정보, 네트워크 소켓까지 전부
open()→read()/write()→close()로 접근
1
2
3
4
5
/dev/ttyS0 → UART 장치
/dev/sda → 스토리지 장치
/proc/1234/mem → PID 1234 프로세스의 메모리
/sys/class/gpio → GPIO 핀
/dev/null → 데이터 버리는 블랙홀
- Linux는 해당 설계 철학을 바탕으로 다음 이점을 가짐
- 애플리케이션이 자원 종류를 몰라도 사용 가능함. UART든 파일이든 소켓이든 동일한 API로 다루므로 코드 복잡도가 감소함
- 셸 파이프라인으로 자원 조합이 가능함.
cat /dev/ttyS0 | grep ERROR처럼 장치 출력을 파이프로 바로 처리하는 것이 가능
디바이스 파일
- Linux에서
/dev/ttyS0와 같이 존재하는 파일이 디바이스 파일이다. /dev폴더에서ls -l명령을 실행하면 다음과 같은 형태로 출력이 나오는 것을 확인할 수 있다.
1
2
3
4
5
6
7
8
9
crw-rw---- 1 root dialout 4, 64 May 5 09:00 ttyS0
│ │ │ │ │ │ │
│ │ │ │ │ │ └ 파일 경로
│ │ │ │ │ └ 최종 수정 시각
│ │ │ │ └ Major, Minor number
│ │ │ └ 그룹 소유자
│ │ └ 사용자 소유자
│ └ 하드링크 수
└ 파일 타입 + 권한
- ls -l 출력의 첫 번째 문자는 파일 타입을 나타내며, 디바이스 파일은 c 또는 b로 구분된다.
| 기호 | 의미 |
|---|---|
- | 일반 파일 |
d | 디렉터리 |
l | 심볼릭 링크 |
c | 문자 디바이스 파일 |
b | 블록 디바이스 파일 |
- 하드링크 수 (1) — 이 파일을 가리키는 하드링크가 몇 개인지. 디바이스 파일은 보통 1이다.
- 사용자 소유자 (root) — 이 파일의 소유자. /dev 아래 디바이스 파일은 대부분 root 소유이다.
- 그룹 소유자 (dialout) — 이 파일에 접근 가능한 그룹. UART 시리얼 포트는 관례적으로 dialout 그룹에 속하며, 일반 사용자가 /dev/ttyS0에 접근하려면 이 그룹에 속해 있어야 한다.
Major/Minor number
- Major number : 해당 디바이스 파일의 드라이버 매핑 번호
- 4번 : TTY 드라이버
- Minor number : 해당 디바이스의 장치 인스턴스 번호
- 같은 드라이버를 사용하는 디바이스 파일에 대해 각각의 식별 번호를 부여함
디바이스 드라이버 실행 흐름
- cat이 open(“/dev/ttyS0”)을 호출한다.
- 이 순간 시스템 콜이 발생하여 CPU가 사용자 공간 → 커널 공간으로 전환된다.
- 커널은 /dev/ttyS0의 Major number 4 를 읽어 드라이버 테이블을 조회한다.
- 드라이버 테이블에서 Major 4 → TTY 드라이버의 open 함수 포인터를 찾아 호출한다.
- cat이 이제 read(“/dev/ttyS0”)를 호출한다. 다시 시스템 콜 발생 → 커널 공간 전환.
- 커널이 TTY 드라이버의 read 함수를 호출하면서 Minor number 64 를 넘긴다.
- TTY 드라이버는 Minor 64를 보고 “0번 UART 장치”임을 파악, 해당 UART 레지스터 주소에 접근하여 데이터를 읽는다.
- 읽은 데이터를 커널 버퍼 → 사용자 공간 버퍼로 복사하여 cat에게 반환한다.
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.