24.01.08 최초 작성
24.01.09 예제 추가
파일에 문자열 read/write
를 통해 HW를 다룰 수 있는 파일 시스템
sysfs
의 파일은 디바이스 드라이버의 정보를 가지고 있으며 class, bus, device 정보를 유저 공간에 전달
mount -t sysfs nodev /sys
로 마운트 가능
kernel object
: sysfs
와 디바이스 모델의 인터페이스 역할struct kobject {
const char *name;
struct list_head entry;
struct kobject *parent;
struct kset *kset;
struct kobj_type *ktype;
struct kernfs_node *sd;
struct kref kref;
...
}
kobject_create_and_add()
: sysfs
에 디렉토리를 생성함struct kobject * kobject_create_and_add (const char * name,
struct kobject * parent);
///
name : kobject의 name 설정
parent : kobject의 parent 설정 (디렉토리 위치를 설정)
NULL 설정 시 /sys 밑에 생성됨
struct kobj_attribute
: sysfs
파일 생성을 위해 필요한 설정__ATTR
매크로를 통해 생성// /source/include/linux/kobject.h
struct kobj_attribute {
struct attribute attr;
ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr,
char *buf);
//cat명령어가 호출했을 때 작동
ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t count);
//echo명령어가 호출했을 때 작동
};
sysfs_create_file()
: sysfs
파일 생성// /source/include/linux/sysfs.h
static inline int __must_check sysfs_create_file(struct kobject *kobj,
const struct attribute *attr)
{
return sysfs_create_file_ns(kobj, attr, NULL);
}
/sys/kernel/ksys/test
를 생성드라이버 등록 | 드라이버 해제 | cat | echo |
---|---|---|---|
kdt_module_init() | kdt_module_exit() | k_show() | k_store() |
sysfs 파일 구조 정의
// 파일의 이름, 권한, 관련 동작(cat, echo) 지정
static struct kobj_attribute test_attr =
__ATTR(test, 0660, k_show, k_store);
// 지정한 파일의 설정을 저장하는 배열
static struct attribute *k_attrs[] = {
&test_attr.attr,
NULL,
};
//
static struct attribute_group k_attr_group = {
.attrs = k_attrs,
};
kdt_module_init()
: ksys
이름의 kobject
자료형을 생성하고 ksys_kobj
로 가르킴, ksys_kobj
아래 앞서 정의한 파일을 링크#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/kobject.h>
static struct kobject *ksys_kobj;
static int __init k_module_init(void)
{
int err = -1;
pr_info("k 커널 모듈 \n");
// kernel_kobj은 커널에서 정의된 전역변수
ksys_kobj = kobject_create_and_add("ksys", kernel_kobj);
if (!ksys_kobj)
return -ENOMEM;
err = sysfs_create_group(ksys_kobj, &k_attr_group);
if (err)
kobject_put(ksys_kobj);
return err;
}
k_show()
: cat 명령어 호출 시 파일의 이름, sysfs_value
에 저장된 값 출력static int sysfs_value;
static ssize_t k_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
size_t len = 0;
pr_info("show adttr.name: %s\n", attr->attr.name);
len = scnprintf(buf, PAGE_SIZE, "%d", sysfs_value);
return len;
}
k_store()
: echo 명령어로 값 입력시 호출, 입력된 값 파일, sysfs_value
에 저장static int sysfs_value;
static ssize_t k_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t len)
{
int val;
if (!len || !sscanf(buf, "%d", &val))
return -EINVAL;
sysfs_value = val;
pr_info("store value: %d\n", val);
return len;
}
kdt_module_exit()
: ksys_kobj
해제static void __exit k_module_exit(void)
{
if (ksys_kobj)
kobject_put(ksys_kobj);
pr_info("바이!!n");
}
/proc/k_proc/kfile
생성드라이버 등록 | 드라이버 해제 | cat | echo |
---|---|---|---|
kdt_module_init() | kdt_module_exit() | k_read() | k_write() |
kdt_module_init()
: /proc
아래 k_proc
디렉토리 생성, /proc/k_proc
아래 k_file
생성static struct proc_dir_entry *proc_dir;
static struct proc_dir_entry *proc_file;
static struct proc_ops fops = {
.proc_read = k_read,
.proc_write = k_write,
};
static int __init k_module_init(void)
{
proc_dir = proc_mkdir("k_proc", NULL);
if(proc_dir == NULL) {
pr_info("procfs_test - Error creating /proc/k_proc\n");
return -ENOMEM;
}
proc_file = proc_create("k_file", 0666, proc_dir, &fops);
if(proc_file == NULL) {
printk("procfs_test - Error creating /proc/hello/k_file\n");
proc_remove(proc_dir);
return -ENOMEM;
}
return 0;
}
k_read()
: cat 명령어 호출 시 procfs read function
출력static ssize_t k_read(struct file *File, char __user *user_buffer, size_t count, loff_t *offs)
{
char buf[] = "procfs read function\n";
return simple_read_from_buffer(user_buffer, count, offs, buf, strlen(buf));
}
k_write()
: echo 명령어 호출 시 사용자 공간에서 커널 공간으로 user_buffer
내용 복사static ssize_t k_write(struct file *File, const char __user *user_buffer, size_t count, loff_t *offs)
{
char buf[255];
int to_copy, not_copied, delta;
memset(buf, 0, sizeof(buf));
to_copy = min(count, sizeof(buf));
not_copied = copy_from_user(buf, user_buffer, to_copy);
pr_info("procfs: %s \n", buf);
delta = to_copy - not_copied;
return delta;
}
kdt_module_exit()
: 생성한 디렉토리, 파일 삭제static void __exit k_module_exit(void)
{
proc_remove(proc_file);
proc_remove(proc_dir);
pr_info("바이!!n");
}