6장에서 우리는, eudev가 빌드될 때 Udev 패키지를 설치했다. 이들의 작동 방식에 대한 자세한 내용을 살펴보기 전에, 과거의 장치 핸들링 방법의 역사에 대해 간단히 짚고 넘어가고자 한다.
일반적인 리눅스
시스템은
전통적으로 정적인
장치 생성 방법을
사용해서, 해당
하드웨어 장치가
실제로 존재하는지
여부에 관계없이
/dev
아래에
매우 많은 장치
노드(때로는 말
그대로 수천 개의
노드)가 만들어졌다.
이는 일반적으로
MAKEDEV
스크립트를 통해
이뤄졌는데, 이
스크립트는 세상에
존재할 수 있는 모든
장치에 대한 관련
주/부 장치 번호와
함께 mknod
프로그램에 대한
여러 호출들을 담고
있었다.
Udev를 사용하면
커널에 의해 탐지된
장치만 해당 장치
노드가 생성된다.
이런 장치 노드는
시스템이 부팅될
때마다 생성되기
때문에 devtmpfs
파일 시스템(완전히
시스템 메모리에
상주하는 가상 파일
시스템)에 저장된다.
장치 노드는 공간이
많이 필요하지 않기
때문에 사용되는
메모리는 무시할 수
있다.
2000년 2월, devfs
라는 새로운
파일 시스템이 2.3.46
커널에 병합되어 2.4
안정 버전 커널에서
사용할 수 있게
되었다. 동적으로
장치를 만드는 이
방법은 비록 커널
소스에 존재는
했으나 핵심 커널
개발자들로부터
결코 지지를 받지
못했다.
devfs
에서
채택된 접근 방식의
주요 문제는 장치
인식, 생성 및 명명
처리 방식이었다.
장치 노드 명명
문제인 후자가
아마도 가장 중요한
사안이었을 것이다.
장치 이름을
설정하는 것이
가능하다면, 장치
명명 정책은 특정
개발자가 아닌
시스템 관리자의
몫이어야 한다는
것이 보편적인
생각이다. 더구나
devfs
파일
시스템은 그 설계
구조상 커널에 대한
실질적인 수정
없이는 고칠 수 없는
교착 상태에
시달렸다. 이는
유지보수가
부실해지자 장기간
폐기된 것으로
표시되었고, 결국
2006년 6월 커널에서
제거되었다.
나중에 2.6 안정
버전으로 배포된 2.5
개발 버전 커널
트리가 개발되면서
sysfs
라는
새로운 가상 파일
시스템이 생겼다.
sysfs
의
역할은 시스템
하드웨어 구성을
유저스페이스
프로세스(userspace
processes)에서 볼 수
있도록 하는 것이다.
이
유저스페이스에서
볼 수 있도록 하는
표현 방식으로 인해,
devfs
에
대응하는
유저스페이스용
대체품 개발
가능성이 훨씬 더
높아졌다.
sysfs
파일
시스템은 위에서
간략히 언급했다.
그렇다면 sysfs
는
시스템에 어떤
장치가
존재하는지, 또 그
장치들에 어떤
장치 번호를
사용해야 하는지를
어떻게 알 수
있을까? 커널
내부로 컴파일된
드라이버는 커널에
의해 감지되는
대로 장치를 sysfs
(내부적으론
devtmpfs)에 직접
등록한다. 모듈로
컴파일된
드라이버는 모듈이
로드될 때
등록된다. sysfs
파일
시스템이
마운트되고나면(/sys에),
드라이버가 sysfs
에 등록한
데이터는
유저스페이스
프로세스와 udevd에서
사용 가능하여
장치 노드 수정을
포함한 처리에
쓰인다.
장치 파일은
커널에 의해 devtmpfs
파일
시스템으로
생성된다. 장치
노드를 등록하려는
모든 드라이버는
devtmpfs
를 통해
(드라이버 코어에
의해) 작업을
수행한다. devtmpfs
인스턴스가 /dev
에
마운트되면, 장치
노드가 고정된
이름과 권한,
소유자를 갖고
초기화되어
생성된다.
그리고나서,
커널은 uevent를 udevd로
보낸다. /etc/udev/rules.d
, /lib/udev/rules.d
, /run/udev/rules.d
디렉토리에 있는
파일들에 지정된
규칙에 따라, udevd는 장치
노드에 대한 추가
심볼릭 링크를
만들거나, 장치
노드 권한, 소유자
또는 그룹을
변경하거나, 해당
개체에 대한 내부
udevd
데이터베이스
항목(이름)을
수정한다.
이 세 디렉토리
안의 규칙들은
번호가 메겨지고
디렉토리들은 모두
병합된다. 만약 udevd가 생성
중인 장치에 대한
규칙을 찾지
못하면, devtmpfs
가 처음
사용된 장치의
권한과 소유권을
남긴다.
모듈로 컴파일된
장치 드라이버에는
별칭(alias)이 내장되어
있을 수 있다.
별칭은 modinfo
프로그램의 출력을
통해 확인할 수
있으며 보통은
모듈이 지원하는
장치의 버스 고유
식별자와 관련이
있다. 예를 들어, snd-fm801
드라이버는 벤더
ID가 0x1319이고 장치 ID가
0x0801인 PCI 장치를
지원하며, “pci:v00001319d00000801sv*sd*bc04sc01i*”라는
별칭을 갖고 있다.
대부분의
장치에서, 버스
드라이버는 sysfs
를 통해
장치를 제어할
드라이버의 별칭을
내보낸다. 다시
말해, /sys/bus/pci/devices/0000:00:0d.0/modalias
파일은 문자열 “pci:v00001319d00000801sv00001319sd00001319bc04sc01i00”을
담고 있다. Udev와 함께
제공되는 기본
규칙은 udevd가 MODALIAS
uevent 환경
변수의 내용(sysfs의
modalias
파일
내용과 같음)으로
/sbin/modprobe를
호출하여,
와일드카드 확장
후 별칭이 이
문자열과 일치하는
모든 모듈을
로드한다.
앞서 제시한 snd-fm801 예시에서는, 구식(그리고 원치 않는) forte 드라이버가 사용 가능하다면, 추가적으로 로드된다는 것을 의미한다. 원치 않는 드라이버 로드를 방지하려면 아래를 참고하라.
커널 자체도 네트워크 프로토콜, 파일 시스템 및 NLS 지원을 위한 모듈을 필요에 따라 로드할 수 있다.
USB MP3플레이어와 같은 장치를 컴퓨터에 연결하면, 커널은 장치가 연결된 것을 인식하고 uevent를 생성한다. 이 uevent는 앞서 설명한 바와 같이 udevd에 의해 처리된다.
장치 노드를 자동으로 생성할 때는 몇 가지 문제가 발생할 수 있다.
Udev는 모듈이 버스
고유 별칭을 갖고
버스 드라이버가
필요한 별칭을 sysfs
로
적절하게 내보내는
경우에만 모듈을
로드할 것이다.
그렇지 않은
경우에는 다른
방법으로 모듈을
로드해야 한다.
Linux-5.5.3에서는, Udev가
제대로 작성된 INPUT, IDE,
PCI, USB, SCSI, SERIO, FireWire 장치용
드라이버들을
로드하는 것으로
알려져 있다.
필요한 장치
드라이버가 Udev에
필요한 사항을
갖고있는지
확인하려면, modinfo에
모듈 이름을
인수로 전달해
실행하라. 이제 /sys/bus
아래에서
장치 디렉토리를
찾고 modalias
파일이 있는지
확인하라.
modalias
파일이
sysfs
에
존재하면,
드라이버는 장치를
지원하고 직접
통신할 수 있지만,
별칭이 없다면
드라이버의
버그이다. Udev의 도움
없이 드라이버를
로드하고 나중에
문제가 수정되길
기대하라.
/sys/bus
아래의
관련 디렉토리에
modalias
파일이
없다면, 이는 커널
개발자들이 아직
이 버스 유형에 modalias
지원을 추가하지
않았음을
의미한다.
Linux-5.5.3에서는, ISA 버스가
이에 해당한다. 이
문제는 이후 커널
버전에서
수정되기를
기대하라.
Udev는 snd-pcm-oss와 같은 “wrapper” 드라이버나 loop와 같은 비하드웨어 드라이버를 로드하기 위한 것이 전혀 아니다.
“wrapper” 모듈이
일부 다른
모듈에서 제공하는
기능만
향상시킨다면(가령,
snd-pcm-oss는 OSS
응용 프로그램에서
사운드 카드를
사용할 수 있게
하여 snd-pcm의
기능을 향상시킴),
Udev가 래핑된 모듈을
로드한 후 래퍼를
로드하도록 modprobe를
구성하라. 이렇게
하려면 해당 /etc/modprobe.d/
파일에 “softdep” 줄을
추가하라. 예를
들면:
<filename>
.conf
softdep snd-pcm post: snd-pcm-oss
“softdep” 명령은
pre:
구문이나 pre:
와 post:
의 혼용도
허용한다는 점을
참고하라. “softdep”
문법 및 기능에
대한 자세한
내용은 modprobe.d(5)
매뉴얼
페이지를
참고하라.
문제의 모듈이
래퍼가 아니며 그
자체로 유용할
경우, 그 모듈을
시스템 부팅 중
로드하도록 modules
부트스크립트를
구성하라. 이렇게
하려면 모듈
이름을 /etc/sysconfig/modules
파일에
별도의 행으로
추가하라. 이것은
래퍼 모듈에도
적용되지만,
그것은
차선책이다.
모듈을 빌드하지
않도록 하거나,
아래의 forte 모듈
예시처럼 /etc/modprobe.d/blacklist.conf
파일에 모듈을
블랙리스트로
추가하라:
blacklist forte
블랙리스트된 모듈도 modprobe 명령을 명시적으로 사용하여 수동으로 로드할 수 있다.
이런 현상은 일반적으로 규칙이 예기치 않게 장치와 일치할 때 발생한다. 예를 들어, 형편없이 작성된 규칙은 SCSI 디스크(의도한 장치)와 해당 벤더의 SCSI 일반 장치(잘못된) 양쪽에 일치할 수 있다. udevadm info 명령의 도움을 받아 위반되는 규칙을 찾고 보다 구체적으로 수정하라.
이것은 앞서
설명한 문제의
또다른 증상일 수
있다. 그렇지 않고
규칙이 sysfs
속성을
사용한다면, 이후
커널에서 수정될
수 있는 커널
타이밍 문제일 수
있다. 당장은
사용된 sysfs
속성을 기다리는
규칙을 만들어 /etc/udev/rules.d/10-wait_for_sysfs.rules
파일에 추가(이
파일이 존재하지
않으면
생성하라)하면
된다. 이렇게 해서
도움이 되었다면 LFS
개발 리스트에
알려주기 바란다.
아래 문단은 드라이버가 커널에 정적으로 구축되었거나 이미 모듈로 로드되어 있으며, Udev가 잘못 명명된 장치를 생성하지 않는 것을 이미 확인했다고 가정한다.
커널 드라이버가
데이터를 sysfs
로
내보내지 않으면
Udev에는 장치 노드를
생성하는 데
필요한 정보가
없다. 이는 커널
트리 외부의 타사
드라이버에서 가장
흔하게 발생한다.
/lib/udev/devices
에
적절한 주/부
번호로 정적 장치
노드를
생성하라(커널
문서 내의 devices.txt
파일이나
타사 드라이버
공급 업체가
제공한 문서를
참고). 정적 장치
노드는 udev에 의해
/dev
에
복사될 것이다.
이는 Udev가 설계상 uevents와 모듈 로드를 병렬로 처리하기 때문에, 순서를 예측할 수 없기 때문이다. 이것은 결코 “수정”되지 않을 것이다. 장치 이름들이 안정적일 것으로 커널에 기대해선 안 된다. 대신, Udev가 설치한 다양한 *_id 유틸리티의 출력이나 일련 번호와 같이, 장치의 안정적인 속성을 기반으로 안정적인 이름을 가진 심볼릭 링크를 만드는 규칙을 직접 생성하라. 예시는 7.4절. “장치 관리”와 7.5절. “일반 네트워크 구성”를 참고하라.
다음 사이트들에서 추가적으로 유용한 문서들을 읽을 수 있다: