본 문서는 Linux booting 문서에서 생략 된 부분이면서 현재 Linux에서 장치관리를 수행하는 udev와 devtmpfs의 상관관계에 대해서 설명하고 있습니다. 또한, devtmpfs의 의미와 역할에 대한 질문의 답변을 정리한 문서이기도 합니다.

  • 마지막수정: 12/22/2015
  • 기존문서와 기술하는 말투를 달리하였으니 양해부탁드립니다.

devfs

먼저 udev가 도입되기 전에 존재 했던 devfs라는 녀석에 대해서 살펴보겠습니다. devfs는 2000년에 도입된 파일시스템으로 장치에 대한 정보를 커널에서 관리 할 수 있도록 만들어진 파일시스템 입니다. 실제 여전히 많은 UNIX 계열 시스템은 devfs를 사용하고 있습니다. 예를 들어 Mac OS X의 경우 BSD Unix 커널 계열이기 때문에 마운트 정보를 보면 devfs를 발견 할 수 있습니다.

$ mount
/dev/disk2 on / (hfs, local, journaled)
devfs on /dev (devfs, local, nobrowse)
map -hosts on /net (autofs, nosuid, automounted, nobrowse)
map auto_home on /home (autofs, automounted, nobrowse)

Linux의 devfs는 UNIX의 devfs와 완전히 같지는 않지만 사용되는 목적은 동일하다고 보시면 됩니다. 이러한 devfs의 역할은 기존에 major, minor 숫자를 통해서 장치 노드(device node)파일을 수작업으로 생성하는 방식 대신에 커널이 장치 이름을 결정 짓고 이를 자동으로 등록해주는 방식입니다. 기존의 정적인 장치 노드 파일을 대체하고 좀 더 능동적으로 관리 할 수 있다는 장점이 있습니다.

다만, 장점 못지 않게 단점과 한계점이 드러났는데 가장 대표적인 부분이 장치를 인식하고 장치 노드를 생성 할 때 사용하는 이름이 문제가 되었습니다. LANANA에서 정책적으로 정리된 이름과 맞지 않았기 때문에 devfs를 실제 물리장치에 있는 /dev로 스위칭 할 때 이름을 맞추기 위해서 좀 더 많은 부가적인 설정이 필요하게 되었고 관리가 복잡하게 되었습니다.

그리고, 이러한 장치 이름 결정 방식이 별로 환영 받지 못하였는지 꽤 오랜기간 개선되거나 수정되지 못하고 방치되고 있다가 2.4 커널에서 널리 사용되던 devfs는 2.6 커널에서 udev로 대체 되기 시작하였고 2006년 커널 2.6.13 에서 사라집니다.

udev

Linux 커널 2.6의 개발버전인 2.5에서 등장한 udev는 아래와 같은 목적으로 만들어 졌습니다.

  • 사용자 영역에서 실행
  • 동적인 장치 노드(/dev) 파일 생성
  • 필요 할 때 지속적으로 동일한 장치명을 제공 할 수 있어야 함
  • 현재 시스템 장치의 정보를 얻을 수 있는 API의 제공

udev는 기본적으로 사용자 모드(user mode/user space)에서 동작하기 때문에 Linux 부팅 과정에서 최대한 빨리 실행되어야 장치 노드 정보를 설정하고 이를 통해 서비스가 올바르게 구동 됩니다. 보통 udev 데몬이 실행 되는 건 rootfs 스위칭이 일어나고 init 프로세스가 구동 되면서 시작됩니다. 하지만, 이러한 방식은 장치 노드 설정이 매우 늦어지게 만드는 문제를 일으키기 때문에 일반적으로 initrd/initramfs 이미지(임시 rootfs 이미지)에 udev와 udev의 기본설정을 포함시켜서 부팅합니다.

이렇게 하면 Linux가 부팅 할 때 실제 디스크장치의 rootfs(/)로 스위칭 작업을 수행하기 전에 메모리에 올라가 rootfs로 사용 중인 initrd/initramfs를 통해서 udev가 실행됩니다. 이렇게 하면 init 전에 장치 노드를 설정 할 수가 있습니다. 아래는 CentOS 6 에서 캡처한 udev 실행 전후의 부트 메시지 입니다.

udev-dmesg.png

사용자 모드에서 동작하는 udev는 어떻게 하드웨어 정보를 확인하고 장치 노드를 등록 하는지에 대한 의문이 들 수 있는데 이는 sysfs 라는 파일시스템을 통해서 해결 하고 있습니다.

sysfs

Linux 2.5 커널 트리에서 등장해서 2.6 안정버전에 등장한 가상 파일시스템인 sysfs는 사용자 모드에서 현재 커널이 가지고 있는 서브시스템(subsystem)과 하드웨어 정보를 보여주는 파일시스템 입니다. 이 파일시스템은 kobject(kernel object)의 정보를 바탕으로 하여 데이터 구조와 속성 정보를 제공합니다. 주로 커널이 인지한 하드웨어 정보를 구조적으로 투영해주고 있으며 이 정보를 바탕으로 udev는 장치 노드를 설정 할 때 어떻게 설정해야하는지를 알게됩니다.

사실 sysfs가 보여주는 하드웨어 정보는 procfs에서도 일부 볼 수 있는데 procfs의 원래 목적이 프로세스 정보를 투영하는 것이었기 때문에 procfs가 보여주는 하드웨어 정보는 procfs의 관리에 혼란을 가중시키게 되었습니다. 따라서, procfs와 별개로 시스템 하드웨어 정보를 체계적으로 보여주는 파일시스템의 필요성이 대두 되었고 그게 sysfs로 나타나게 되었습니다.

devtmpfs

devfs 2.0이라고 불리우기도 하는 devtmpfs는 기본적으로 tmpfs의 일종 입니다. tmpfs는 흔히 ramdisk와 비교되기도 하는데 ramdisk와의 큰 차이점은 아래와 같습니다.

  • tmpfs는 모든 내용을 커널 내부 캐시메모리에 저장합니다
  • page cache에 올라갈 수 있는 구조이기 때문에 swap 장치로 swap out도 가능합니다
    • 즉, 메모리에 항상 존재하는게 아니라 상황에 따라 swap 장치(디스크 등)로 저장이 됨

tmpfs의 일종인 devtmpfs가 등장하게 된 이유는 간단합니다. Linux 부팅 시간의 단축을 위해서 입니다. udev가 전체적인 장치 노드를 생성 및 관리를 하더라도 필요 할 때 연결하는 USB 같은 장치가 아닌이상 대부분의 장치는 이미 시스템에 고정적으로 존재하기 때문에 커널이 부팅 할 때 인식하고 필요한 모듈의 로딩이 가능합니다. 그래서 initrd/initramfs에서 udev가 장치 노드를 등록하기도 전에 커널이 시작하는 시점에 장치 노드를 등록 할 수 있는 파일시스템을 생성하고 /dev에 마운트를 하게 되면 실제 rootfs(/) 파티션으로 스위칭하고 init 과정을 마친 후에도 계속해서 유지할 수 있는 파일시스템을 갖게 됩니다.

다시말해, 대부분의 장치에 대해서 장치 노드를 커널 부팅 초반에 생성해서 유지/관리 할 수 있기 때문에 사용자 모드에서의 장치 노드 생성/관리보다 매우 빨리 처리 할 수 있고 tmpfs 기반의 파일시스템이기 때문에 사용자 모드에서도 활용이 가능한 장점을 갖게 됩니다.

요약

devfs는 지원가능한 장치노드를 major, minor 번호로 관리하며 모두 생성하는 정적인 방식보다는 나았지만 사용자 모드에서의 접근성과 장치 노드 관리가 좋지 않았기 때문에 이를 대체 할 수 있는 udev를 통해서 장치 노드를 관리하는 방안이 도입되었으며 여기에 부팅 시간 개선을 위해 devtmpfs가 도입이 되었습니다.