10/03/2014

Linux의 udev 와 sys filesystem 이해 (수정 및 정리-1)

1. Background

가끔 udevd 없는 filesystem이 존재하여, 매번 자동화의 필요성을 느끼며, Kernel 의 sys filesystem 및 udevd의 기능을 필요로 하여 관련부분을 정리하고자 한다.

오래전에는 Application 에서 Driver의 상태의 알어서 HW 이벤트 알고 다시 다른 Driver를 제어하려면
항상 애플리케이션 프로그램과 통신을 해서 알아내고 제어를 해야만 했다.
하지만, udev와 sys filefs가 나온 이후로 이 문제들이 간단히 해결이 되고 관리가 편해졌다.
간단한 예가 usb의 hotplug일 것이며, 이를 확장해서 사용도 가능하다.


1.1 NETLINK의 이해  

udev에서 Kernel과 UserInterface 사이를 쉽게 통신하기위해서 사용되는 IPC로 사용방법은 socket으로 사용하고, 중요한 것은 udev의 uevent의 전달일 것 같다.

  • NETLINK의 사용방식 및 구조
 int socket(AF_NETLINK, SOCK_DGRAM ''or'' SOCK_RAW, ''protocol'') 


protocol은 NETLINK_xxx 로 다양하게 지원하며, uevent는 NETLINK_KOBJECT_UEVENT
Netlink 사용방법 및 세부내용은 아래의 사이트 참고
  https://en.wikipedia.org/wiki/Netlink
  https://yhcting.tistory.com/entry/Linux-kobject-uevent-in-kernel

  • NETLINK의  Kernel 과 User 실제사용의 예 
TEST Program은 기본 NETLINK만 테스트 (uevent는 제외)
  1. NETLINK 테스트 Instruction
  2. NETLINK TEST Kernel Module   (protocl: NETLINK_USER 사용)
  3. NETLINK TEST User Interface    (socket(PF_NETLINK, SOCK_RAW, NETLINK_USER) 사용)

  https://stackoverflow.com/questions/3299386/how-to-use-netlink-socket-to-communicate-with-a-kernel-module
  https://gist.github.com/JeonghunLee/17db624665da91ee46c221b00e2b93f5



  • Kernel의 uevent 의 이해 
Kernel에서 제공해주는 uevent 관련함수들을 알아보자
  https://elixir.bootlin.com/linux/v4.2/source/lib/kobject_uevent.c#L386
  https://elixir.bootlin.com/linux/v4.2/source/lib/kobject_uevent.c#L414
  http://egloos.zum.com/furmuwon/v/11024590


1.2 D-BUS
Linux Application에서 사용하는 일종의 IPC의 한 종류로 기존에는 일대일 방식였지만, Message Bus system 개념형태로 변경되어 통신을 한다.

기본적인 동작형태는 D-Bus Instance와 중개자인 D-BUS Damon과 Socket으로 연결형태라고 생각하면된다.
아래에서 제공해주는 그림을 보면 쉽게 이해가 간다.

세부내용은 Wiki 참고
  https://en.wikipedia.org/wiki/D-Bus
  https://www.freedesktop.org/wiki/Software/dbus/
  https://dbus.freedesktop.org/doc/api/html/group__DBusMessage.html
  http://makersweb.net/lecture/16441


1.3 sysfs 의 이해

sysfs는 system filesystem의 약어이며, 이를 이용하여, USER에서 device driver의 상태확인 및 제어 쉽게 가능하다 

Kernel에서 만들어주는 Filesystem이기에, 각 Device driver에서 제공을 해주어야 하며,실제 Filesystem에서는 sysfs로 mount만 해주면 동작이 된다.
기존 /proc 와 다른 점은 /proc의 경우 상태확인만 가능했지만, /sys는 설정가능하다.

대표적인 예로 GPIO 설정을 쉽게 User에서 쉽게 변경가능하지만, Device Driver에서 제공을 해주어야하기에, Device Driver 마다 사용법이 다를 수 있다.

  https://en.wikipedia.org/wiki/Sysfs

sys filesystem의 실제 사용의 예제
  http://processors.wiki.ti.com/index.php/DSS2_SYSFS_Examples


1.4 udev의 기본이해

udev는 userspace 의 /dev로 주로 hotplug 와 hw event에 주로 사용되며, /dev 의 deivce node를 관리를 주목적으로 한다.

Linux device driver에 특정 HW event (hotplug)가 발생하면, User에서는 /dev의 device node를 필요시 새로 생성할 필요가 있다.

Kernel에서는 Netlink로 User에게 uevent를 전달하면, udevd에서 새로운 /dev/의 device node를 생성가능 하며,
그리고 더불어 User에서 정한 udev rule에 의해서

udev 는 NETLINK 통신하여 uevent를 받아 udev의 rule에 맞게 적용을 된 부분을 D-BUS를 이용하여 통신한다.

  • udev의 기본동작 
Kernel ----------> udev -----> Network Manager <--> D-Bus <--> Evolution
       (netlink socket)            (libudev를 사용한 damon )



  • udev의 daemon과 에 관련 tool
  1. libudev : systemd 이 사용이 하며, d-bus를 이용하기 위해서 사용되어짐.
  2. udevd :  user 영역에서  virtual /dev를 관리하며 netlink로 통신하며, uevent를 감지
  3. udevadm :  진단목적으로 만들어진 utility 라고 한다. 


  • udev의 Rules 
  1. /lib/udev/rules.d/  -규칙은 각각의 꾸러미가 설치하며, 보통 사용자가 바꾸어선 안됩니다.
  2. /etc/udev/rules.d/ - 최종유저가 설정한 규칙이 이라고하며, 새로운 규칙은 이곳에해야한다


  • 기본사항 참고
  https://en.wikipedia.org/wiki/Udev


  • Kernel 설정 및 기본설정방법 참고
  https://wiki.gentoo.org/wiki/Udev/ko


  • /lib/udev/rules.d  Manual 및 설정의 예 관련사항
  http://www.reactivated.net/writing_udev_rules.html
  https://docs.oracle.com/cd/E37670_01/E41138/html/ch07s03.html
  https://access.redhat.com/documentation/ko-KR/Red_Hat_Enterprise_Linux/6/html/Logical_Volume_Manager_Administration/udev_device_manager.html
  http://chaoxifer.egloos.com/viewer/1752706   (USB Auto mount)
  https://code.google.com/p/yad/wiki/USBFlash
  http://www.hanbit.co.kr/network/view.html?bi_id=1425
  https://access.redhat.com/documentation/ko-KR/Red_Hat_Enterprise_Linux/6/html/Logical_Volume_Manager_Administration/udev_device_manager.html#tb-udev-for-devicemap


2. udev 와 sysfs의 기본동작 

  1. udev를 이용하여, sysfs를 이용하는 방법
  2. udev를 이용하여 application에서 감지 

  • 동작-1  udevd과 Application 에서 감지
  1. device driver는 netlink를 이용하여 uevent를 발생 
  2. udevd는이를 감지하고 알아내고, 중복 uevents 들을 삭제한다. 
  3. udevd는 이 udev event process 에게 전달한다
  4. /xxx/udev/rules.d rules을 memory에 저장 및 parsing하여 rule 적용후 udev database 생성 
  5. 이를 d-bus를 이용하여 다른 App들에게 공유한다. 
  6. 최종 application은 d-bus를 통해 이를 감지하고 동작한다. 

  • 동작-2  sysfs 동작
  1. Kernel은 kobject_create 만들고 이를 sysfs를 속성 및 uevent 정보 생성 (/dev 관련정보)  
  2. uevent를 발생되면 sysfs 정보를 이용하여 /dev에 device node를 추가 

  http://kroah.com/log/blog/2013/06/26/how-to-create-a-sysfs-file-correctly/
  http://dynamicbu.egloos.com/m/3048465


그림은 상위 두가지 루틴을 다 설명해주며, 핵심은 udev event process이다.
출처: http://blogas.sysadmin.lt/?p=141

아래의 기본구조를 이해를 Driver 순서부터 보는 것이 좋고, uevent라는 HW Event message로 udevd이 이를 관리하고, udev event process에 전달하는 것이다.
이는 /etc/udev/rules.d/에서 설정 및 관리가 가능하다.

구조파악하기가 쉬움
  http://sonseungha.tistory.com/323


2.1 sysfs와 udev Kernel 실제동작예  

아래는 rtc driver의  udev 와 sys file system 의 좋은 예제이며, uevent의 봐야할 부분은 kobject_uevent_env 부분을 보면 기본동작이 이해가 간다
  1. user에서 rtc module 커널에 등록 
  2. rtc_init 함수는 misc_register->class_device_register를 호출 
  3. kobject_add 후 /sys/class/misc/rtc 의 base directory 생성 
  4. /sys/class/misc/rtc/uevent 생성 ( device name or interface 제공 )
  5. /sys/class/misc/rtc/dev 생성  ( /dev/rtc의  major/minor number 제공)
  6. kobject_uevent->kobject_uevent_env  호출되어 uevent의 환경설정과 uevent발생
  7. netlink에 의해 uevent 함께 환경값이 udevd에 의해 /dev/rtc 생성 (4번 ,5번정보)
  8. 설정된 uevent 환경값을 udev rule에 적용하여 추가동작 

/proc/sys/kernel/hotplug 이 부분도 연관이 있다고 하는데, 이부분은 추후파악


출처: http://www.embeddedlinux.org.cn/EssentialLinuxDeviceDrivers/final/ch04lev1sec3.html

udev 및 udevadm 사용 및 rule 관련내용
  https://wiki.archlinux.org/index.php/udev

udev와 sysfs 관련 분석
  http://furmuwon.egloos.com/m/11024590

  • udev의 정보확인방법 
udevadm를 이용하여 쉽게 udev rules의 정보를 넣어 쉽게 구현이 가능하다.

$ udevadm info -a -n /dev/sda1

  looking at device '/devices/platform/s5p-ehci/usb1/1-2/1-2.3/1-2.3.3/1-2.3.3:1.0/host0/target0:0:0/0:0:0:0/block/sda/sda1':
    KERNEL=="sda1"
    SUBSYSTEM=="block"
    DRIVER==""
    ATTR{partition}=="1"


  http://www.troot.co.kr/tc/1958
  https://stackoverflow.com/questions/36009559/sd-card-how-to-force-the-kernel-to-read-the-wp-pin-again-without-removing-the-s
  https://www.pks.mpg.de/~mueller/docs/suse10.1/suselinux-manual_en/manual/cha.udev.html

3. udev의 device 설정 

아래와 같이 설정추가

$ vi /etc/udev/rules.d/10-usbdisk.rules
....
SUBSYSTEMS="usb", ENV{ID_FS_USAGE}=="filesystem", ENV{UDISKS_MOUNT_OPTIONS}="rw"
....