Udev?
Udev는 A Userspace Implementation of devfs 의 약자로서 실제로 존재하는 장치에 대한 파일만을 포함하는 동적 장치 디렉토리를 제공한다. 보통 /dev/ 디렉토리에 장치 노드 파일들을 만들거나 제거한다. /dev/ 디렉토리는 udev 설정에서 변경 할 수 있다.
Udev의 특징
- Run in userspace
- 유저 공간(Userspace) 에서 동작하며, 이는 hotplug + sysfs 를 이용하여 가능하다.
- Udev는 hotplug 서브시스템의 일부로서, 만일 장치가 시스템에 추가되거나 제거되면 hotplug 에 의해 udev 가 호출된다. udev는 hotplug 이벤트를 받아 sysfs 에서 필요한 정보를 얻어 /dev/ 장치 파일을 생성한다.
- 뒤에 설명할 장치 파일 이름에 대한 정책에 정책이 유저 공간에서 설정 가능하다.
- Create a dynamic /dev
- Provide flexible & consistent device naming, if wanted
- udev 설정에서 정규 표현식으로 설정이 가능하다.
- 고정 장치(persitent) 파일도 지원한다. 예를들어 특정 시리얼을 가지는 USB 디스크를 항상 장치 파일을 /dev/usb_disk 만들도록 설정할 수 있다.
- 또한, 장치 파일 이름 / 심볼릭 링크 / 허가권(permission) 을 설정 할 수 있다.
- Provide a userspace API to access info avout current system devices
- 응용 프로그램에서 현재 연결된 혹은 제거된 장치에 대한 정보를 알아야 할 필요가 있을 경우 libsysfs 를 통해 알 수 있도록 API를 제공한다.
또한, udev 는 장치 연결 및 제거시 D-BUS 메세지를 생성하고 응용 프로그램에게 이벤트를 전달 할 수 있다.
Udev 동작 방식
장치 생성시, udev는 라벨, 시리얼 번호 또는 버스 장치 번호와 같은 장치 속성을 수집하기 위해 주어진 장치의 sysfs 디렉토리를 읽는다. 이 속성은 장치의 고유한 이름을 결정하는 열쇠로 사용될 수 있다. udev는 시스템에 존재하는 장치에 대한 정보를 DB(/dev/.udev/)에 유지한다. 장치 제거시, udev 는 삭제될 장치의 파일을 찾기 위해 DB를 검색한다.
모듈이 적재되면, hotplug에 의해 udev 가 호출되고, 장치가 추가되거나 제거된다. 만일 장치가 디바이스 드라이버와 통신할 수 있는 메이저와 마이너 번호를 포함하고 있는 "dev" 파일을 드라이버가 제공하면, udev 는 /sys/ 디렉토리를 살펴본다. 장치 파일명과 심볼릭 링크를 지정하는 /etc/udev/rules.d/ 디렉토리에 있는 udev 규칙들을 살펴본후, 장치 파일은 /etc/udev/40-permissions.rules 에 지정된 허가권으로 /dev/ 에 생성된다.
장치 파일을 생성 혹은 제거 한후 udev 는 /etc/udev/80-programs.rule 에서 프로그램을 실행한다. 이후 응용 프로그램에서 장치에 대한 정보를 알 수 있도록 D-BUS 이벤트를 발생시킨다.
Udev 구성 요소
udev 는 다음의 3개로 구성되어 있다.
- udev
- namedev(udev rules)
- libsysfs
udev rules
udev rules 은 장치 파일과 관련된 정책이다. /etc/udev/rules.d/* 에 있다. 다음은 간단한 udev rules 예이다.
# USB Epson printer to be called lp_epson
LABEL, BUS="usb", serial="HX0LL0012202323480", NAME="lp_epson"
# USB HP printer to be called lp_hp.
LABEL, BUS="usb", serial="W09090207101241330", NAME="lp_hp"
# sound card with PCI bus id 00:0b.0 to be the first sound card
NUMBER, BUS="pci", id="00:0B.0", NAME="dsp"
# sound card with PCI bus id 00:07.1 to be the second sound card
NUMBER, BUS="pci", id="00:07.1", NAME="dsp1"
# USB mouse plugged into the third port of the first hub to be
# called mouse0
TOPOLOGY, BUS="usb", place="1.3", NAME="mouse0"
# USB tablet plugged into the second port of the second hub to be
# called mouse1
TOPOLGY, BUS="usb", place="2.2", NAME="mouse1"
# ttyUSB1 should always be called visor
REPLACE, KERNEL="ttyUSB1", NAME="visor"
Udev 이용
ODCAP 장치에 대한 장치 파일을 /dev/dvr 로 생성하고, 허가권을 444, 소유권을 root.yanggun 으로 설정해보겠다.
먼저 odcap 장치 인식시 dvr로 인식되도록 /etc/udev/rules.d/20-names.rules 파일에 다음을 추가한다.
KERNEL=="odcap[0-9]*" NAME="dvr/%k"
소유권과 허가권은 /etc/udev/rules.d/40-permissions.rules 파일에 다음을 추가한다.
KERNEL=="odcap[0-9]*" MODE="0444", GROUP="yanggun"
/dev/dvr 로 심볼릭 링크가 생기도록 /etc/udev/rules.d/60-symlinks.rules 파일에 다음을 추가한다.
KERNEL=="odcap[0-9]*" SYMLINK+="dvr"
위와 같이 수정한 후 시스템을 재시작하면, 아래와 같이 인식된다.
yanggun@ubuntu-yanggun:/dev/dvr$ pwd
/dev/dvr
yanggun@ubuntu-yanggun:/dev/dvr$ ls -al
합계 0
drwxr-xr-x 2 root root 60 2006-08-29 19:15 .
drwxr-xr-x 16 root root 15020 2006-08-29 19:16 ..
cr--r--r-- 1 root yanggun 97, 0 2006-08-29 19:15 odcap0
yanggun@ubuntu-yanggun:/dev/dvr$
다음은 udev DB 에 기록된 내용이다.
yanggun@ubuntu-yanggun:/etc/udev/rules.d$ cat /dev/.udev/db/class@odcap@odcap0
N:odcap0
S:dvr
M:97:0
다음은 sysfs 의 내용이다.
yanggun@ubuntu-yanggun:/etc/udev/rules.d$ udevinfo -a -p /sys/class/odcap/odcap0/
udevinfo starts with the device the node belongs to and then walks up the
device chain, to print for every device found, all possibly useful attributes
in the udev key format.
Only attributes within one device section may be used together in one rule,
to match the device for which the node will be created.
device '/sys/class/odcap/odcap0' has major:minor 97:0
looking at class device '/sys/class/odcap/odcap0':
KERNEL=="odcap0"
SUBSYSTEM=="odcap"
SYSFS{dev}=="97:0"
SYSFS{name}=="odcap0"
follow the "device"-link to the physical device:
looking at the device chain at '/sys/devices/pci0000:00/0000:00:1e.0/0000:03:04.0':
BUS=="pci"
ID=="0000:03:04.0"
DRIVER=="ODCAPBD"
SYSFS{class}=="0x040000"
SYSFS{device}=="0x120a"
SYSFS{irq}=="185"
SYSFS{local_cpus}=="ff"
SYSFS{modalias}=="pci:v00009914d0000120Asv00000000sd00000000bc04sc00i00"
SYSFS{subsystem_device}=="0x0000"
SYSFS{subsystem_vendor}=="0x0000"
SYSFS{vendor}=="0x9914"
looking at the device chain at '/sys/devices/pci0000:00/0000:00:1e.0':
BUS=="pci"
ID=="0000:00:1e.0"
DRIVER=="unknown"
SYSFS{class}=="0x060400"
SYSFS{device}=="0x244e"
SYSFS{irq}=="0"
SYSFS{local_cpus}=="ff"
SYSFS{modalias}=="pci:v00008086d0000244Esv00000000sd00000000bc06sc04i00"
SYSFS{subsystem_device}=="0x0000"
SYSFS{subsystem_vendor}=="0x0000"
SYSFS{vendor}=="0x8086"
looking at the device chain at '/sys/devices/pci0000:00':
BUS==""
ID=="pci0000:00"
DRIVER=="unknown"