sysfs

EEEFFEE·2024년 1월 8일
0

임베디드 리눅스

목록 보기
8/14
post-thumbnail

24.01.08 최초 작성
24.01.09 예제 추가

1. sysfs filesystem

  • 파일에 문자열 read/write를 통해 HW를 다룰 수 있는 파일 시스템

  • sysfs의 파일은 디바이스 드라이버의 정보를 가지고 있으며 class, bus, device 정보를 유저 공간에 전달

  • mount -t sysfs nodev /sys로 마운트 가능

1.2 kernel object

  • 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 밑에 생성됨

1.2.1 sysfs 파일 생성

  • 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);
}

예제

sysfs

  • /sys/kernel/ksys/test를 생성
드라이버 등록드라이버 해제catecho
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");
}

procfs

  • /proc/k_proc/kfile 생성
드라이버 등록드라이버 해제catecho
kdt_module_init()kdt_module_exit()k_read()k_write()
  • kdt_module_init() : /proc아래 k_proc디렉토리 생성, /proc/k_proc아래 k_file생성
    cat, echo 명령어 사용 시 호출될 함수 등록

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");
}

0개의 댓글

관련 채용 정보