2018년 3월 26일 월요일

linux DEVICE_ATTR 분석


cat /proc/meminfo 를 하는 경우 node_read_meminfo() 함수가 호출됨

/drivers/base/node.c
static DEVICE_ATTR(meminfo, S_IRUGO, node_read_meminfo, NULL);

 * @ DEVICE_ATTR(_name, _mode, _show, _store)
 * _name : 인자로 주어진 이름이 sysfs의 파일 이름이 된다.
 * _mode : 파일의 권한을 준다.
 * _show : show 함수를 등록한다. -> node를 read할 때 호출되는 함수
 * _store : store 함수를 등록한다. -> node에 write할 때 호출 되는 함수

/include/linux/device.h
#define DEVICE_ATTR(_name, _mode, _show, _store) \
 struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
#define DEVICE_ATTR_RW(_name) \
 struct device_attribute dev_attr_##_name = __ATTR_RW(_name)
#define DEVICE_ATTR_RO(_name) \
 struct device_attribute dev_attr_##_name = __ATTR_RO(_name)
#define DEVICE_ATTR_WO(_name) \
 struct device_attribute dev_attr_##_name = __ATTR_WO(_name)

/include/linux/sysfs.h
#define __ATTR(_name, _mode, _show, _store) {    \
 .attr = {.name = __stringify(_name),    \
   .mode = VERIFY_OCTAL_PERMISSIONS(_mode) },  \
 .show = _show,      \
 .store = _store,      \
}
=>__stringify() 함수로 인해 위의 meminfo가 string 형태로 변환됩니다.

/include/linux/sysfs.h
#define __ATTR(_name, _mode, _show, _store) {    \
 .attr = {.name = __stringify(_name),    \
   .mode = VERIFY_OCTAL_PERMISSIONS(_mode) },  \
 .show = _show,      \
 .store = _store,      \
}

#define __ATTR_PREALLOC(_name, _mode, _show, _store) {   \
 .attr = {.name = __stringify(_name),    \
   .mode = SYSFS_PREALLOC | VERIFY_OCTAL_PERMISSIONS(_mode) },\
 .show = _show,      \
 .store = _store,      \
}

#define __ATTR_RO(_name) {      \
 .attr = { .name = __stringify(_name), .mode = S_IRUGO }, \
 .show = _name##_show,      \
}

#define __ATTR_WO(_name) {      \
 .attr = { .name = __stringify(_name), .mode = S_IWUSR }, \
 .store = _name##_store,     \
}

#define __ATTR_RW(_name) __ATTR(_name, (S_IWUSR | S_IRUGO),  \
    _name##_show, _name##_store)

아래 형태의 변수를 만들게 됩니다.
static DEVICE_ATTR(meminfo, S_IRUGO, node_read_meminfo, NULL);

=>


static struct device_attribute dev_attr_meminfo = { .attr = {.name = "meminfo",
.mode = VERIFY_OCTAL_PERMISSIONS(_mode) }, .show = node_read_meminfo,

.store = NULL,


};

이것은 아래 코드에 의해서 dev_attr_meminfo.attr 주소를 넘김으로서 처리가 됩니다.

/drivers/base/node.c
tatic struct attribute *node_dev_attrs[] = {
 &dev_attr_cpumap.attr,
 &dev_attr_cpulist.attr,
 &dev_attr_meminfo.attr,
 &dev_attr_numastat.attr,
 &dev_attr_distance.attr,
 &dev_attr_vmstat.attr,
 NULL
};
ATTRIBUTE_GROUPS(node_dev);


Preview:/include/linux/sysfs.h
#define ATTRIBUTE_GROUPS(_name)     \
static const struct attribute_group _name##_group = {  \
 .attrs = _name##_attrs,     \
};        \
__ATTRIBUTE_GROUPS(_name)

Preview:/include/linux/sysfs.h
#define __ATTRIBUTE_GROUPS(_name)    \
static const struct attribute_group *_name##_groups[] = { \
 &_name##_group,      \
 NULL,       \
}
static const struct attribute_group node_dev_group = {
 .attrs = node_dev_attrs,
};
static const struct attribute_group *node_dev_groups[] = {
 &node_dev_group,
 NULL,
}



_mode 의 인자 sys/stat.h 참고

File mode bits:
S_IRWXU
read, write, execute/search by owner
S_IRUSR
read permission, owner
S_IWUSR
write permission, owner
S_IXUSR
execute/search permission, owner
S_IRWXG
read, write, execute/search by group
S_IRGRP
read permission, group
S_IWGRP
write permission, group
S_IXGRP
execute/search permission, group
S_IRWXO
read, write, execute/search by others
S_IROTH
read permission, others
S_IWOTH
write permission, others
S_IXOTH
execute/search permission, others
S_ISUID
set-user-ID on execution
S_ISGID
set-group-ID on execution
S_ISVTX
on directories, restricted deletion flag



댓글 없음:

댓글 쓰기