리눅스 디바이스 드라이버 모델의 초기화
리눅스 디바이스 드라이버 모델을 표현하기위해 kobject 및 kset등이 사용된다.
- sysfs는 kobject 및 kset 등으로 이루어진 하이라키 관계를 sysfs 가상 파일 시스템을 통해 표현되고 관리된다.
다음 그림은 디바이스 드라이버 모델의 초기화 호출 과정을 보여준다.
driver_init()
drivers/base/init.c
/** * driver_init - initialize driver model. * * Call the driver model init functions to initialize their * subsystems. Called early from init/main.c. */ void __init driver_init(void) { /* These are the core pieces */ devtmpfs_init(); devices_init(); buses_init(); classes_init(); firmware_init(); hypervisor_init(); /* These are also core pieces, but must come after the * core core pieces. */ platform_bus_init(); cpu_dev_init(); memory_dev_init(); container_dev_init(); of_core_init(); }
리눅스 커널이 사용하는 드라이버 모델의 초기화를 수행한다.
- 코드 라인 10에서 devtmpfs 파일 시스템을 마운트하고 kdevtmpfs 스레드를 생성하고 동작시킨다.
- 참고: devtmpfs & kdevtmpfs 스레드 | 문c
- 코드 라인 11에서 디바이스를 표현 및 관리할 “/sys/devices” 및 “/sys/dev” 디렉토리를 생성한다. 또한 캐릭터 디바이스를 표현 및 관리할 “/sys/dev/block” 디렉토리와 블럭 디바이스를 표현 및 관리할 “/sys/dev/char” 디렉토리를 생성한다.
- 코드 라인 12에서 버스 디바이스를 표현 및 관리할 “/sys/bus” 디렉토리를 생성한다. 또한 서브 시스템들이 등록될 “/sys/devices/system” 디렉토리도 생성한다.
- 코드 라인 13에서 클래스 디바이스를 표현 및 관리할 “/sys/class” 디렉토리를 생성한다.
- 코드 라인 14에서 펌웨어를 표현 및 관리할 “/sys/firmware” 디렉토리를 생성한다.
- 코드 라인 15에서 하이퍼바이저를 표현 및 관리할 “/sys/hypervisor” 디렉토리를 생성한다.
- 코드 라인 20에서 플랫폼 디바이스를 표현 및 관리할 “/sys/devices/platform” 디렉토리와 “/sys/bus/platform” 디렉토리를 생성한다.
- 코드 라인 21에서 cpu 서브시스템의 cpu들을 표현 및 관리할 “/sys/devices/system/cpu” 디렉토리와 그 아래에 속성 파일들을 생성한다.
- 코드 라인 22에서 hotplug 허용된 시스템에서 memory 서브시스템의 memory 블럭들을 표현 및 관리할 “/sys/devices/system/memory” 디렉토리와 그 아래에 속성 파일들을 생성한다.
- 코드 라인 23에서 컨테이너 서브시스템의 컨테이너들을 표현 및 관리할 “/sys/devices/system/container” 디렉토리를 생성한다.
- 코드 라인 24에서 디바이스 트리를 표현 및 관리할 “/sys/firmware/devicetree” 디렉토리를 생성하고, 그 이하에 모든 노드에 대한 디렉토리를 만든다. 그리고 각 노드의 속성들도 해당 노드 디렉토리에 각각 파일로 추가한다.
devices_init()
drivers/base/core.c
int __init devices_init(void) { devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL); if (!devices_kset) return -ENOMEM; dev_kobj = kobject_create_and_add("dev", NULL); if (!dev_kobj) goto dev_kobj_err; sysfs_dev_block_kobj = kobject_create_and_add("block", dev_kobj); if (!sysfs_dev_block_kobj) goto block_kobj_err; sysfs_dev_char_kobj = kobject_create_and_add("char", dev_kobj); if (!sysfs_dev_char_kobj) goto char_kobj_err; return 0; char_kobj_err: kobject_put(sysfs_dev_block_kobj); block_kobj_err: kobject_put(dev_kobj); dev_kobj_err: kset_unregister(devices_kset); return -ENOMEM; }
디바이스를 표현 및 관리할 “/sys/devices” 및 “/sys/dev” 디렉토리를 생성한다. 또한 캐릭터 디바이스를 표현 및 관리할 “/sys/dev/block” 디렉토리와 블럭 디바이스를 표현 및 관리할 “/sys/dev/char” 디렉토리를 생성한다.
- 코드 라인 1~3에서 “devices” 이름을 갖는 kset를 생성하고 sysfs 루트에 추가한다.
- 코드 라인 4~6에서 “dev” 이름을 갖는 kobject를 생성하고 sysfs 루트에 생성한다.
- 코드 라인 7~9에서 “block” 이름을 갖는 kobject를 생성하고 “/sys/dev” 뒤에 추가한다.
- 코드 라인 10~12에서 “char” 이름을 갖는 kobject를 생성하고 “/sys/dev” 뒤에 추가한다.
buses_init()
drivers/base/bus.c
int __init buses_init(void) { bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL); if (!bus_kset) return -ENOMEM; system_kset = kset_create_and_add("system", NULL, &devices_kset->kobj); if (!system_kset) return -ENOMEM; return 0; }
버스 디바이스를 표현 및 관리할 “/sys/bus” 디렉토리를 생성한다. 또한 서브 시스템들이 등록될 “/sys/devices/system” 디렉토리도 생성한다.
- 코드 라인 3~5에서 “bus” 이름을 갖는 kset를 생성하고 sysfs 루트에 추가한다.
- 코드 라인 7~9에서 “system” 이름을 갖는 kset를 생성하고 “/sys/devices” 뒤에 추가한다.
classes_init()
drivers/base/class.c
int __init classes_init(void) { class_kset = kset_create_and_add("class", NULL, NULL); if (!class_kset) return -ENOMEM; return 0; }
클래스 디바이스를 표현 및 관리할 “/sys/class” 디렉토리를 생성한다.
- 코드 라인 3~5에서 “class” 이름을 갖는 kset를 생성하고 sysfs 루트에 추가한다.
firmware_init()
drivers/base/firmware.c
int __init firmware_init(void) { firmware_kobj = kobject_create_and_add("firmware", NULL); if (!firmware_kobj) return -ENOMEM; return 0; }
펌웨어를 표현 및 관리할 “/sys/firmware” 디렉토리를 생성한다.
- 코드 라인 3~5에서 “firmware” 이름을 갖는 kobject를 생성하고 sysfs 루트에 추가한다.
hypervisor_init()
drivers/base/hypervisor.c
int __init hypervisor_init(void) { hypervisor_kobj = kobject_create_and_add("hypervisor", NULL); if (!hypervisor_kobj) return -ENOMEM; return 0; }
하이퍼바이저를 표현 및 관리할 “/sys/hypervisor” 디렉토리를 생성한다.
- 코드 라인 3~5에서 “hypervisor” 이름을 갖는 kobject를 생성하고 sysfs 루트에 추가한다.
platform_bus_init()
drivers/base/platform.c
int __init platform_bus_init(void) { int error; early_platform_cleanup(); error = device_register(&platform_bus); if (error) return error; error = bus_register(&platform_bus_type); if (error) device_unregister(&platform_bus); of_platform_register_reconfig_notifier(); return error; }
플랫폼 디바이스를 표현 및 관리할 “/sys/devices/platform” 디렉토리와 “/sys/bus/platform” 디렉토리를 생성한다.
- 코드 라인 5에서 early 플랫폼 디바이스를 리스트에서 제거한다.
- 코드 라인 7~9에서 플랫폼 버스 디바이스를 등록한다.
- 플랫폼 버스 디바이스를 표현하고 관리할 “/sys/devices/platform” 디렉토리를 생성한다.
- 코드 라인 10~12에서 플랫폼 버스를 등록한다.
- 플랫폼 버스를 표현하고 관리할 “/sys/bus/platform” 디렉토리를 생성한다.
- 코드 라인 13에서 디바이스 트리를 통해 플랫폼 디바이스가 추가/삭제될 때 마다 호출되도록 notifier block에 of_platform_notify() 함수를 등록한다.
등록될 디바이스
struct device platform_bus = { .init_name = "platform", }; EXPORT_SYMBOL_GPL(platform_bus);
등록될 버스
struct bus_type platform_bus_type = { .name = "platform", .dev_groups = platform_dev_groups, .match = platform_match, .uevent = platform_uevent, .pm = &platform_dev_pm_ops, }; EXPORT_SYMBOL_GPL(platform_bus_type);
예) 다음은 platform 버스 디바이스 아래에 등록된 플랫폼 디바이스들이다.
$ ls /sys/devices/platform -la drwxr-xr-x 3 root root 0 May 16 15:00 20020000.pcie drwxr-xr-x 3 root root 0 Mar 15 09:55 50020000.pcie drwxr-xr-x 3 root root 0 May 16 15:00 60c00000.pcie drwxr-xr-x 3 root root 0 May 28 16:17 Fixed MDIO bus.0 drwxr-xr-x 2 root root 0 May 28 16:17 alarmtimer drwxr-xr-x 2 root root 0 May 28 16:17 pmu drwxr-xr-x 2 root root 0 May 28 16:17 psci drwxr-xr-x 2 root root 0 May 28 16:17 secure_rtc drwxr-xr-x 2 root root 0 May 28 16:17 serial8250 drwxr-xr-x 70 root root 0 Mar 30 15:41 soc drwxr-xr-x 2 root root 0 May 28 16:17 timer -rw-r--r-- 1 root root 4096 May 28 16:17 uevent
early_platform_cleanup()
drivers/base/platform.c
/** * early_platform_cleanup - clean up early platform code */ void __init early_platform_cleanup(void) { struct platform_device *pd, *pd2; /* clean up the devres list used to chain devices */ list_for_each_entry_safe(pd, pd2, &early_platform_device_list, dev.devres_head) { list_del(&pd->dev.devres_head); memset(&pd->dev.devres_head, 0, sizeof(pd->dev.devres_head)); } }
등록된 early 플랫폼 디바이스들을 리스트에서 제거한다.
- early_platform_add_devices() 함수로 추가한 플랫폼 디바이스이다.
- arm64에서는 early 플랫폼 디바이스를 등록하지 않는다.
- 디바이스 트리를 통해 플랫폼 디바이스가 추가/삭제될 때 마다 of_platform_notify() 후크 함수가 호출되도록 등록한다.
of_platform_register_reconfig_notifier()
drivers/of/platform.c
void of_platform_register_reconfig_notifier(void) { WARN_ON(of_reconfig_notifier_register(&platform_of_notifier)); }
디바이스 트리를 통해 플랫폼 디바이스가 추가/삭제될 때 마다 호출되도록 notifier block에 of_platform_notify() 함수를 등록한다.
- CONFIG_OF_DYNAMIC 및 CONFIG_OF_ADDRESS 두 커널 옵션이 사용되어야 동작한다.
- 참고: Platform Device | 문c
cpu_dev_init()
drivers/base/cpu.c
void __init cpu_dev_init(void) { if (subsys_system_register(&cpu_subsys, cpu_root_attr_groups)) panic("Failed to register CPU subsystem"); cpu_dev_register_generic(); cpu_register_vulnerabilities(); }
cpu 서브시스템의 cpu들을 표현 및 관리할 “/sys/devices/system/cpu” 디렉토리와 그 아래에 속성 파일들을 생성한다.
- 코드 라인 3~4에서 cpu 서브 시스템을 등록하고 그 밑에 속성들을 추가한다.
- “/sys/devices/system/cpu” 디렉토리를 만들고 그 밑에 다음 속성들을 추가한다.
- probe, release, online, possible, present, offline, isolated, nohz_full, modalias
- “/sys/devices/system/cpu” 디렉토리를 만들고 그 밑에 다음 속성들을 추가한다.
- 코드 라인 6~7에서 CONFIG_GENERIC_CPU_DEVICES 커널 옵션을 사용하는 경우 호출되지만 arm64 아키텍처는 관련 없다.
다음은 cpu 서브 시스템에 해당하는 버스 타입이다.
struct bus_type cpu_subsys = { .name = "cpu", .dev_name = "cpu", .match = cpu_subsys_match, #ifdef CONFIG_HOTPLUG_CPU .online = cpu_subsys_online, .offline = cpu_subsys_offline, #endif }; EXPORT_SYMBOL_GPL(cpu_subsys);
다음은 cpu 서브 시스템에 추가될 속성들이다.
static struct attribute *cpu_root_attrs[] = { #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE &dev_attr_probe.attr, &dev_attr_release.attr, #endif &cpu_attrs[0].attr.attr, &cpu_attrs[1].attr.attr, &cpu_attrs[2].attr.attr, &dev_attr_kernel_max.attr, &dev_attr_offline.attr, &dev_attr_isolated.attr, #ifdef CONFIG_NO_HZ_FULL &dev_attr_nohz_full.attr, #endif #ifdef CONFIG_GENERIC_CPU_AUTOPROBE &dev_attr_modalias.attr, #endif NULL };
cpu 서브 시스템에 등록된 속성들을 간단히 알아본다.
- probe
- CONFIG_ARCH_CPU_PROBE_RELEASE 커널 옵션이 필요하다.
- release
- CONFIG_ARCH_CPU_PROBE_RELEASE 커널 옵션이 필요하다.
- online
- 현재 online 된 cpu를 보여준다. (장착되고 online된 상태의 cpu)
- 예) 0-1
- possible
- possible cpu를 보여준다. (장착 되었거나 추가 장착 가능한 상태의 cpu)
- 예) 0~3
- present
- preseent cpu를 보여준다. (장착된 상태의 cpu)
- 예) 0~1
- kernel_max
- 현재 부팅된 커널이 지원하는 최고 cpu 번호 (NR_CPUS -1)
- 예) 3
- 현재 부팅된 커널이 지원하는 최고 cpu 번호 (NR_CPUS -1)
- offline
- offline된 cpu를 보여준다.
- 예) 2~3
- offline된 cpu를 보여준다.
- isolated
- isolate된 cpu를 보여준다. (스케줄링에서 제외된 cpu)
- 예) 기본적으로는 없으므로 아무것도 보여주지 않는다.
- isolate된 cpu를 보여준다. (스케줄링에서 제외된 cpu)
- nohz_full
- nohz full된 상태의 cpu를 보여준다.
- CONFIG_NO_HZ_FULL 커널 옵션이 필요하다.
- modalias
- cpu 타입과 feature들을 보여준다.
- 예) cpu:type:aarch64_be:feature:,0000,0001,0003,0004,0005,0006,0007
- CONFIG_GENERIC_CPU_AUTOPROBE 커널 옵션이 필요하다.
- arm, arm64, mips, s390, x86 등 많은 아키텍처들이 이 커널 옵션을 사용한다.
예) 다음은 cpu 서브 시스템에 등록된 cpu들과 속성들이다.
- cpu0 ~ cpu3과 같은 cpu 디렉토리들은 cpu가 online/offline될 때마다 추가/제거된다.
$ ls /sys/devices/system/cpu -la drwxr-xr-x 4 root root 0 May 28 16:50 cpu0 drwxr-xr-x 4 root root 0 May 28 16:50 cpu1 drwxr-xr-x 2 root root 0 May 28 16:50 cpu2 drwxr-xr-x 2 root root 0 May 28 16:50 cpu3 drwxr-xr-x 2 root root 0 May 28 16:50 cpufreq drwxr-xr-x 2 root root 0 May 28 16:50 cpuidle -r--r--r-- 1 root root 4096 May 28 16:50 isolated -r--r--r-- 1 root root 4096 May 28 16:50 kernel_max -r--r--r-- 1 root root 4096 May 28 16:50 modalias -r--r--r-- 1 root root 4096 May 28 16:50 offline -r--r--r-- 1 root root 4096 Mar 15 09:55 online -r--r--r-- 1 root root 4096 May 28 16:50 possible -r--r--r-- 1 root root 4096 May 28 16:50 present -rw-r--r-- 1 root root 4096 May 28 16:50 uevent
예) 다음은 cpu0에 대한 속성들이다.
<pre “>$ ls /sys/devices/system/cpu/cpu0 -la drwxr-xr-x 5 root root 0 May 28 17:12 cache -r——– 1 root root 4096 May 28 17:12 frequency lrwxrwxrwx 1 root root 0 May 28 17:12 of_node -> ../../../../firmware/devicetree/base/cpus/cpu@0 -rw-r–r– 1 root root 4096 May 28 17:12 online lrwxrwxrwx 1 root root 0 May 28 17:12 subsystem -> ../../../../bus/cpu drwxr-xr-x 2 root root 0 May 28 17:12 topology -rw-r–r– 1 root root 4096 May 28 17:12 uevent
memory_dev_init()
drivers/base/memory.c
/* * Initialize the sysfs support for memory devices... */ int __init memory_dev_init(void) { unsigned int i; int ret; int err; unsigned long block_sz; ret = subsys_system_register(&memory_subsys, memory_root_attr_groups); if (ret) goto out; block_sz = get_memory_block_size(); sections_per_block = block_sz / MIN_MEMORY_BLOCK_SIZE; /* * Create entries for memory sections that were found * during boot and have been initialized */ mutex_lock(&mem_sysfs_mutex); for (i = 0; i < NR_MEM_SECTIONS; i += sections_per_block) { /* Don't iterate over sections we know are !present: */ if (i > __highest_present_section_nr) break; err = add_memory_block(i); if (!ret) ret = err; } mutex_unlock(&mem_sysfs_mutex); out: if (ret) printk(KERN_ERR "%s() failed: %d\n", __func__, ret); return ret; }
hotplug 허용된 시스템(CONFIG_MEMORY_HOTPLUG_SPARSE 커널 옵션)에서 memory 서브시스템의 memory 블럭들을 표현 및 관리할 “/sys/devices/system/memory” 디렉토리와 그 아래에 속성 파일들을 생성한다.
- 코드 라인 11~13에서 memory 서브시스템을 등록하고 관련 속성을 추가한다.
- “/sys/devices/system/memory” 디렉토리를 만들고 그 밑에 다음 속성들을 추가한다.
- probe, soft_offline_page, block_size_bytes, auto_online_blocks
- “/sys/devices/system/memory” 디렉토리를 만들고 그 밑에 다음 속성들을 추가한다.
- 코드 라인에서 15~16에서 블럭당 섹션 수를 산출한다.
- arm64는 블럭과 섹션 크기가 같으므로 항상 1이다.
- 코드 라인 22~32에서 전체 섹션에 대해서 블럭 크기만큼 증가시키며 memory 서브시스템 밑에 메모리 블럭(디렉토리 및 파일들)을 추가한다.
다음은 memory 서브 시스템에 해당하는 버스 타입이다.
static struct bus_type memory_subsys = { .name = MEMORY_CLASS_NAME, .dev_name = MEMORY_CLASS_NAME, .online = memory_subsys_online, .offline = memory_subsys_offline, };
다음은 memory 서브 시스템에 추가될 속성들이다.
static struct attribute *memory_root_attrs[] = { #ifdef CONFIG_ARCH_MEMORY_PROBE &dev_attr_probe.attr, #endif #ifdef CONFIG_MEMORY_FAILURE &dev_attr_soft_offline_page.attr, &dev_attr_hard_offline_page.attr, #endif &dev_attr_block_size_bytes.attr, &dev_attr_auto_online_blocks.attr, NULL }; static struct attribute_group memory_root_attr_group = { .attrs = memory_root_attrs, }; static const struct attribute_group *memory_root_attr_groups[] = { &memory_root_attr_group, NULL, };
예) 다음은 memory 서브 시스템에 등록된 메모리 블럭들과 속성들이다.
- memory0 ~ memory27과 같은 memory 블럭 디렉토리들은 memory가 online/offline될 때마다 추가/제거된다.
$ ls -la -r--r--r-- 1 root root 4096 5월 29 14:14 block_size_bytes --w------- 1 root root 4096 5월 29 14:14 hard_offline_page drwxr-xr-x 3 root root 0 5월 29 14:18 memory0 drwxr-xr-x 3 root root 0 5월 29 13:36 memory1 ... drwxr-xr-x 3 root root 0 5월 29 13:36 memory27 drwxr-xr-x 2 root root 0 5월 29 14:14 power --w------- 1 root root 4096 5월 29 14:14 probe --w------- 1 root root 4096 5월 29 14:14 soft_offline_page -rw-r--r-- 1 root root 4096 5월 29 13:36 uevent
예) 다음은 memory0 블럭에 대한 속성들이다.
$ ls /sys/devices/system/memory/memory0 -la lrwxrwxrwx 1 root root 0 5월 29 14:18 node0 -> ../../node/node0 -rw-r--r-- 1 root root 4096 5월 29 14:18 online -r--r--r-- 1 root root 4096 5월 29 14:18 phys_device -r--r--r-- 1 root root 4096 5월 29 14:18 phys_index drwxr-xr-x 2 root root 0 5월 29 14:18 power -r--r--r-- 1 root root 4096 5월 29 14:18 removable -rw-r--r-- 1 root root 4096 5월 29 14:18 state lrwxrwxrwx 1 root root 0 5월 29 14:18 subsystem -> ../../../../bus/memory -rw-r--r-- 1 root root 4096 5월 29 14:18 uevent -r--r--r-- 1 root root 4096 5월 29 14:18 valid_zones
get_memory_block_size()
drivers/base/memory.c
static unsigned long get_memory_block_size(void) { unsigned long block_sz; block_sz = memory_block_size_bytes(); /* Validate blk_sz is a power of 2 and not less than section size */ if ((block_sz & (block_sz - 1)) || (block_sz < MIN_MEMORY_BLOCK_SIZE)) { WARN_ON(1); block_sz = MIN_MEMORY_BLOCK_SIZE; } return block_sz; }
메모리 블럭 사이즈를 반환한다.
- 아키텍처에 별도의 구현이 없는 디폴트: 섹션 사이즈(arm64)
container_dev_init()
drivers/base/container.c
void __init container_dev_init(void) { int ret; ret = subsys_system_register(&container_subsys, NULL); if (ret) pr_err("%s() failed: %d\n", __func__, ret); }
컨테이너 서브시스템의 컨테이너들을 표현 및 관리할 “/sys/devices/system/container” 디렉토리를 생성한다. (추가할 속성들은 없다)
다음은 container 서브 시스템에 해당하는 버스 타입이다.
struct bus_type container_subsys = { .name = CONTAINER_BUS_NAME, .dev_name = CONTAINER_BUS_NAME, .online = trivial_online, .offline = container_offline, };
of_core_init()
drivers/of/base.c
void __init of_core_init(void) { struct device_node *np; /* Create the kset, and register existing nodes */ mutex_lock(&of_mutex); of_kset = kset_create_and_add("devicetree", NULL, firmware_kobj); if (!of_kset) { mutex_unlock(&of_mutex); pr_err("failed to register existing nodes\n"); return; } for_each_of_allnodes(np) __of_attach_node_sysfs(np); mutex_unlock(&of_mutex); /* Symlink in /proc as required by userspace ABI */ if (of_root) proc_symlink("device-tree", NULL, "/sys/firmware/devicetree/base"); }
디바이스 트리를 표현 및 관리할 “/sys/firmware/devicetree” 디렉토리를 생성하고, 그 이하에 모든 노드에 대한 디렉토리를 만든다. 그리고 각 노드의 속성들도 해당 노드 디렉토리에 각각 파일로 추가한다.
- 코드 라인 8~12에서 “devicetree” kset을 생성하고 “/sys/firmware”에 추가한다.
- “/sys/firmware/devicetree” 디렉토리를 만든다.
- 코드 라인 13~14에서 “/sys/firmware/devicetree” 디렉토리 밑에 읽어온 디바이스 트리 노드들과 속성들을 추가한다.
- 첫 번째 루트 노드는 base 라는 이름의 디렉토리에 존재한다.
- 코드 라인 18~19에서 “/sys/firmware/devicetree/base”를 가리키는 심볼릭 링크를 proc 루트 디렉토리에 만든다.
- “/proc/device-tree” 심볼릭 링크 파일을 생성한다.
예) 루트 디렉토리인 base 아래에 생긴 노드들과 속성들이다.
$ ls /sys/firmware/devicetree/base -la -r--r--r-- 1 root root 4 Mar 30 15:45 #address-cells -r--r--r-- 1 root root 4 Mar 30 15:45 #size-cells drwxr-xr-x 2 root root 0 Mar 30 15:45 aliases drwxr-xr-x 2 root root 0 Mar 30 15:45 bootst drwxr-xr-x 2 root root 0 Mar 30 15:45 chosen -r--r--r-- 1 root root 22 Mar 30 15:45 compatible drwxr-xr-x 7 root root 0 Mar 30 15:45 cpus -r--r--r-- 1 root root 4 Mar 30 15:45 interrupt-parent drwxr-xr-x 2 root root 0 Mar 30 15:45 memory -r--r--r-- 1 root root 14 Mar 30 15:45 model -r--r--r-- 1 root root 1 Mar 30 15:45 name drwxr-xr-x 2 root root 0 Mar 30 15:45 pcie@20020000 drwxr-xr-x 2 root root 0 Mar 30 15:45 pcie@50020000 drwxr-xr-x 2 root root 0 Mar 30 15:45 pcie@60c00000 drwxr-xr-x 2 root root 0 Mar 30 15:45 pmu drwxr-xr-x 2 root root 0 Mar 30 15:45 psci drwxr-xr-x 2 root root 0 Mar 30 15:45 secure_rtc drwxr-xr-x 70 root root 0 Mar 30 15:45 soc drwxr-xr-x 2 root root 0 Mar 30 15:45 timer
참고
- Device & Driver -1- (Device Driver Model) | 문c
- Device & Driver -2- (Bus & Class) | 문c
- Device & Driver -3- (Platform device) | 문c
- Sysfs (kobject & kset) | 문c
- driver_init() | 문c – 현재 글
- devtmpfs & kdevtmpfs 스레드 | 문c
- do_initcalls() | 문c
- Linux Device Model Part 1 | Sarah Diesburg – 다운로드 pdf
- Linux Device Model Part 2 | Sarah Diesburg – 다운로드 pdf
- Linux Device Drivers | OPERSYS – 다운로드 pdf
- Embedded data structures and lifetime management | Shuah Khan, Samsung Open Source Group – 다운로드 pdf
- The Sysfs Virtual Filesystem Exploring the Linux Device Model | Bill Gatliff – 다운로드 pdf
- Linux Device Drivers | Jie Liao – 다운로드 pdf
- The zen of kobjects | LWN.net
- Linux Device Drivers, Third Edition | LWN.net
- kobject/kset/ktype documentation and example code updated | LWN.net
- Documentation/driver-model/ | kernel.org
- Brief sysfs Tutorial | Ben Marks – 다운로드 pdf
- Rules on how to access information in sysfs | kernel.org