Thursday, August 23, 2007

페도라 삽질기 6 - udev, hal, gnome-volume-properties, gnome-mount

언제부터인가 USB drive를 꽂으면 owner가 root로 설정이 되어서 불편하던 참에 종강과 더불어 드디어 짬이 났다. 막연히 udev 설정이 잘못 되었으리라는 생각으로 시작을 했지만 결국에는 hal과 gnome-mount 설정까지 뒤적거리는 삽질로 이어지게 되었다.

1.udev
udev는 동적으로(dynamically) /dev 디렉토리 내의 디바이스 파일을 생성 & 제거해주는 프로그램이다. 예를 들어 usb 프린터를 꽂게 되면 1) 커널이 이를 감지하고 /sbin/hotplug를 이용해서 새로운 디바이스 추가 이벤트를 발생하고, 2) udev는 그 이벤트를 받아 적당한 이름의 디바이스 파일(또는 심볼릭 링크)을 /dev 디렉토리 밑에 만들어 주는 것이다. 뽑는 경우에는 물론 그 디바이스 파일을 제거해준다. udev 전에는 커널이 직접 ram상에서 디바이스 파일(또는 노드)들을 관리하는 devfs가 쓰였는데 커널 영역에서 돌아가는 프로세스이므로 유저영역, 즉 어플리케이션이 할 수 있는 일은 거의 없었다. 그래서 등장한 것이 udev이다. udev의 u는 user 영역(즉 어플리케이션 영역) 을 말한다. hotplug는 커널 2.6에서부터 도입되었는데, 사실은 이미 그 이전에 usb나 IEEE1394와 같은 수시로 추가/제거가 가능한 장치들의 등장으로 인하여 특정시점에 하드웨어가 연결되거나 제거되면 해당 하드웨어로터 관련 정보를 실시간으로 얻어 전체적인 시스템 정보를 업데이트하는 sysfs기술은 이미 도입되어 있었다. 이런 맥락에서 본다면 udev가 가능하게 된 배경에는 hotplug와 sysfs가 있다고 보아도 좋을 것 같다.

udev의 설정파일은 "디바이스 파일 이름을 정하는 규칙을 정하고 있는 /etc/udev/rules.d/디렉토리 밑의 [*.rules] 파일들과 디바이스의 퍼미션을 설정하는 /etc/udev/permissions.d/디렉토리 밑의 [*.rules] 파일들이 있다"고 페도라 3를 기준으로 설명한 어떤 인터넷 문서에는 나와 있는데... 페도라 6에 깔린 udev 0.95에는 맞지 않는 것 같다. /etc/udev/ 밑에는 기본적으로 rules.d 디렉토리만 있고 permissions.d 디렉토리는 없다. 아마도 permissions.d 디렉토리를 만들고 그 밑에 .rules 파일을 만든다면 이전 버전과의 호환성 차원에서 동작할 지도 모르지만, rules.d 밑에 놓이는 .rules 파일에 uid와 umask를 설정할 수 있는데 특별히 다른 파일에 퍼미션을 설정할 필요가 있을까?

udev는 새로운 디바이스가 추가되면 특정한 프로그램이 실행되도록 *.rules 파일을 설정할 수 있다. 따라서 usb 디스크가 컴퓨터에 꽂히면 그 디스크를 마운트하고 소유자와 그룹을 설정할 수 있다. 하지만 페도라6에 기본적으로 제공되는 udev rules 파일은 기냥 /dev 밑에 동적으로 해당 디바이스 파일만 만들 뿐 해당 드라이버를 로드하거나 마운트를 해주거나 하지는 않는다. 그래서 결론은 udev는 내 문제와 상관이 없다는 거~~~. 왜냐하면 내 시스템의 경우에는 usb thumb drive을 꽂으면 /media/disk에 자동으로 마운트해서 nautilus로 그 내용을 보여 주는데, 이런 기능은 페도라6에 기본적으로 적용된 udev rules 파일을 아무리 찾아봐도 설정되어 있지 않았기 때문이다. 그래서 포커스를 다음 용의자인 hal로 이동.

P.S. 하지만 udev는 특정한 디바이스를 /dev 밑의 특정한 장치(e.g. /dev/myUsbDisk)에 연결되도록 하는 경우에는 매우 유용하다. 예를 들어 컴퓨터에 usb포트가 4개가 있지만 내가 어느 곳에 샘숭 YP-2 usb drive를 꽂던 간에 /dev/YP-2에 연결되도록 해야하고, cron으로 매일 /dev/YP-2를 백업하도록 쉘 스크립트를 만들어 놓았을 경우. 여기에 대한 예를 아래 링크에서 찾아볼수 있다. http://www.g-loaded.eu/2005/09/18/udev/

2.HAL(Hardware Abstract Layer)

개념적으로는 hal은 사용자 어플리케이션과 커널과의 사이에 하드웨어를 다루는 중간 계층(layer)이라 보면 될 듯하다. 다시말해, 기존의 어플리케이션-커널-디바이스 드라이버 계층에 하나를 추가해서 어플리케이션- hal-커널-디바이스 드라이버의 계층로 만드는 것이다. 이러한 계층추가로 얻게 되는 잇점은 어플리케이션 개발자나 커널 개발자가 각 하드웨어로 부터 좀 더 독립적인 프로그래밍을 할 수 있게 된다. UML로 따지면 어댑터(파사드인가?) 비스므리 한걸로 생각하면 될 듯... 내가 알기로는 HAL 개념의 도입은 윈도우즈가 리눅스보다 좀 빨랐던 듯 하다. 아래 그림은 freedesktop.org의 웹사이트인 http://people.freedesktop.org/~david/hal-spec/hal-spec.html에서 발췌한 hal의 개념도이다. 그림을 클릭하면 큰 그림을 볼 수 있다.

hal은 새로운 디바이스가 추가 되면, 그 디바이스에 vendor가 내장한 product 정보, 커널이 수집한 디바이스의 main/minor 넘버 등 정보, 그리고 필요하다면 유저에게 다이얼로그 상자를 띄워 그 디바이스에 관련된 정보를 입력받는 방법으로 여러 소스에서 그 하드웨어에 관련된 정보를 수집한 후 자체 데이터 베이스에 넣고 관리한다. 그리고 그 디바이스를 다른 어플리케이션들이 활용할 수 있도록 필요한 API를 제공하는 것은 물론이다. 그리고 무엇보다도 중요한 한가지는 새로운 디바이스 추가 이벤트( 즉, 커널의 hotplug 시그널)가 발생하면 이를 커널영역과 어플리케이션 영역을 관통하는 D-Bus를 통하여 각 어플리케이션에게 notify한다는 것이다. hal의 설정 파일은 페도라6의 경우 /usr/share/hal/ 밑에 놓여 있는데 주로 디바이스의 정체(?)를 파악하기 위한 /usr/share/hal/information/ 밑의 .fdi파일 (XML형식의 파일이다) 과 그 디바이스에 어떤 드라이버를 로드한다든지 관련 옵션은 어떤 것들인지를 파악하기 위한 /usr/share/hal/fdi/policy/ 및의 .fdi 파일로 구성되어 있다. 만약 필요하다면 특정한 디바이스가 플러그 인 되는 경우 D-Bus를 통하여 각 어플리케이션에게 notify하기 전에 특정한 프로그램이 실행되도록(예를 들어 특정한 쉘변수를 설정한다던가 아니면 사용자에게 다이얼로그 화면을 띄우는) policy 파일의 "callout" attribute를 설정할 수 있다. 여기에 대한 좋은 예는 디지털 카메라 프로그램인 gphoto2이다. 이프로그램을 설치하면 디지털 카메라가 플러그 인되는 경우 /usr/libexec/gphoto-set-procperm을 실행하도록 callout이 설정된 policy 파일이 같이 설치되는데, gphoto-set-procperm 프로그램은 그 카메라의 퍼미션을 적절하게 설정하는 기능을 수행한다. 링크는 요기http://www.gphoto.org/doc/manual/permissions-usb.html. 이 링크에서는 callout을 어떻게 policy 파일에 써 넣는 지와 callout에 연결된 프로그램이 대충 어떻게 구성되는지 gphoto-set-procperm의 쉘 스크립트 소스코드를 볼 수있다. 기타 hal과 관련해서 읽어볼 만한 자료는 여기를 참조. http://www.redhat.com/magazine/003jan05/features/hal/.

실제로 페도라3에서는 새로운 디스크가, 자세히는 파일시스템을 가진 volume,추가되는 경우 fstab-sync라는 callout 프로그램이 실행되도록 패키징되어 있었다. 이 프로그램은 파일시스템을 가진 디스크가 추가되는 경우 동적으로 /etc/fstab을 수정하는 기능을 담당하였다. 좀 더 자세한 내용은 위의 레드햇사의 링크를 참조. 근데 그 이후로는, 당연히 페도라 6를 포함해서, fstab-sync라는 프로그램이 폐기되었다는 것. 그럼 뭔가? 도대체 어떤 프로그램이 내가 usb 드라이브를 꽂으면 이걸 /media/disk/에 마운트해서 nautilus로 그걸 보여주는 것일까?

3. gnome-volume-properties & gnome-mount
정답은 요놈들이었다. 결국은 페도라6에서 hal은 하드웨어에 대한 정보를 모아 놓지만 실제로 callout으로 지정된 프로그램이 없는 이상 D-Bus를 통해 "이런 하드웨어가 하나 추가되었소" 혹은 "제거되었소" 라는 통보 이상의 특별한 행동을 안한다는 말씀 (여기서 어떤 드라이버를 로드할 거냐 하는 문제는 별론으로 하자) . 그리고 gnome-volume-properties는 hal로부터 이 통보를 받게 되면 유저가 설정한 셋팅에 따라 마운트를 한다든가 하는 액션을 취하게 된다. 아래는 gnome-volume-properties의 설정화면.

gnome-volume-properties가 마운트를 해야하는 경우 gnome-mount라는 프로그램이 사용되는데 각 파일시스템(예: vfat)별로 마운트 옵션(예: uid=)은 다시 윈도우즈로 말하자면 레지스트리에 해당하는 gconf에 저장되어 있다. 구글에서 gnome-mount에서 사용할 수 있는 마운트 옵션을 찾아봤는데 결과는 신통치 않았다. 아마도 그냥 mount에서 사용할 수 있는 옵션은 모두 사용할 수 있는 것으로 추측된다. 대신 gnome-mount의 man 페이지에서 uid옵션과 관련해서 특이한 점을 찾았는데 특별한 유저 아이디를 명시하지 않고 그냥 uid= 옵션만 주면 현재 사용자가 적용된다는 것이다. 바로 이것이 내가 원하던 거였다. 이렇게 쉬웠던 걸 udev를 찾고 hal을 뒤졌으니...

원래 "uid="옵션은 gonome-mount 패키지를 설치하면 디폴트로 잡히게 되어 있는 옵션이나 내 컴퓨터에서는 웬일인지 gnome-mount의 스키마가 인식되어 있지 않았다. 분명 /etc/gconf/schemas/에 gnome-mount.schemas화일은 존재하는데 gconf에는 등록되어 있지 않았다. 원래 rpm으로 설치하면 포스트 런 스크립트로 gconf에 등록이 되게 되어 있는데... 스키마는 별다른게 아니라 그냥 각종 옵션들의 타입(예: string)과 디폴트 값 정도를 기록해 놓은 xml형식의 파일이다. 아뭏튼 gconftool-2을 이용해서 스키마를 먼저 등록해줘야 했다.

gconftool-2 --install-schema-file=/etc/gconf/gnome-mount.schemas

일단 등록이 되면 gconf는 gconf-editor를 통해서 수정해 줄 수도 있고, 사용자 홈 아래의 .gconf 디렉토리의 xml 파일을 직접 수정해 줄수도 있다. 아래는 수정된 내 ~/.gconf/system/storage/default_options/vfat/%gconf.xml파일과 gconf-editor의 스크린 샷이다. 내친 김에 shortname=winnt옵션과 utf8 옵션도 추가했다. euc-kr인코딩을 쓴다면 codepage=949(맞나 모르겠네?) 옵션도 추가할 수 있을 것이다.
<?xml version="1.0"?>
<gconf>
<entry name="mount_options" mtime="1187666380" type="list" ltype="string">
<li type="string">
<stringvalue>uid=</stringvalue>
</li>
<li type="string">
<stringvalue>shortname=winnt</stringvalue>
</li>
<li type="string">
<stringvalue>utf8</stringvalue>
</li>
</entry>
</gconf>


0 Comment: