리눅스 디바이스 드라이버 모델의 초기화
리눅스 디바이스 드라이버 모델을 표현하기위해 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
