-
[LINUX][KERNEL] sysfs attribute 구조체 및 매크로 상속 관계Linux/kernel 2023. 8. 3. 02:28
목적
- 어느 날 문득 sysfs attribute를 만들려고 하는데, ATTR과 DEVICE_ATTR 중에 뭘 써야할 지 고민했다. 그래서 정리를 좀 해보려고 한다.
내용
- 결론부터 말하면 모든 *_DEVICE_ATTR[_*] 패밀리들은 결국 ATTR[_*]을 상속한다. 결국 최상위가 ATTR[_*]란 소리이다.
구조는 아래와 같다.
/include/linux/sysfs.h struct attribute { const char *name; umode_t mode; #ifdef CONFIG_DEBUG_LOCK_ALLOC bool ignore_lockdep:1; struct lock_class_key *key; struct lock_class_key skey; #endif }; ... ... /include/linux/device.h struct device_attribute { struct attribute attr; ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf); ssize_t (*store)(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); }; ... ... /include/linux/iio/sysfs.h struct iio_dev_attr { struct device_attribute dev_attr; u64 address; struct list_head l; struct iio_chan_spec const *c; }; ... ... struct sensor_device_attribute{ struct device_attribute dev_attr; int index; };
구조체 상속 구조는 다음과 같다.
- struct sensor_device_attribute -> 제일 최하위
- struct iio_dev_attr
- struct device_attribute
- strcut attribute -> 제일 최상위
- struct device_attribute
구조체의 상속 구조와 다르게 매크로는 조금 다르다.
#define DEVICE_ATTR(_name, _mode, _show, _store) \ struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store) ... ... #define SENSOR_ATTR(_name, _mode, _show, _store, _index) \ { .dev_attr = __ATTR(_name, _mode, _show, _store), \ .index = _index } ... ... #define IIO_ATTR(_name, _mode, _show, _store, _addr) \ { .dev_attr = __ATTR(_name, _mode, _show, _store), \ .address = _addr } ... ... #define __ATTR(_name, _mode, _show, _store) { \ .attr = {.name = __stringify(_name), \ .mode = VERIFY_OCTAL_PERMISSIONS(_mode) }, \ .show = _show, \ .store = _store, \ }
매크로 상속 구조는 다음과 같다.
- DEVICE_ATTR
- SENSOR_ATTR
- IIO_ATTR
- __ATTR
매크로 구조에서 주의할 점이 있다. 구조체 변수를 정적으로 선언해주는 매크로와 구조체 변수는 선언하지 않고, 그 안에 값을 채워주는 매크로로 나눌 수 있다.
/* - 정적으로 변수를 해주는 매크로 - 예를 들어, DEVICE_ATTR(yohda, 0644, NULL, NULL); 를 작성하면 dev_attr_yohda 라는 변수를 정적으로 선언한다. */ #define DEVICE_ATTR(_name, _mode, _show, _store) \ struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store) /* - 정적으로 변수를 선언해주지 않는다. - struct sensor_device_attribute yohda_attr = SENSOR_ATTR(yohda, 0644, NULL, NULL, 0); 과 같이 작성해야 한다. */ #define SENSOR_ATTR(_name, _mode, _show, _store, _index) \ { .dev_attr = __ATTR(_name, _mode, _show, _store), \ .index = _index }
결론
- 나는 주로 간단한 몇 개 되지 않는 2~3개 정도의 attribute들은 정적 선언 매크로를 사용한다. 그러나 hwmon나 iio쪽 driver 코드들을 보면 group 단위의 많은 attribute가 필요할 때는, 속성을 채워주는 형식의 매크로를 많이 사용한다.
'Linux > kernel' 카테고리의 다른 글
[리눅스 커널] Symmetric Multi-Processing(SMP) (0) 2023.08.03 [리눅스] Linux kernel headers (0) 2023.08.03 [LINUX][KERNEL] sysfs store/show 함수의 반환값 (0) 2023.08.03 [리눅스 커널] Interrupt - high level reference (0) 2023.08.03 [리눅스 커널] platform driver probe를 호출하는 4가지 방법. (0) 2023.08.03