Skip to content

모듈과 장치 관리

1. 정의

  • 모듈: 커널 관련 하위 함수, 데이터, 바이너리 이미지를 포함해 동적으로 불러 올 수 있는 커널 객체를 의미한다.
  • 장치: 리눅스 커널은 장치를 블록 장치, 캐릭터 장치, 네트워크 장치 3가지로 분류한다. 모든 장치 드라이버가 물리장치를 표현하는 것은 아니며 커널 난수 생성기, 메모리 장치처럼 가상 장치도 표현한다.

2. 모듈 사용하기

모듈 만들기

  • 모듈 개발은 새로운 프로그램을 짜는 것과 비슷하다.

  • 각 모듈은 소스파일 내에 자신의 시작위치(module_init())와 종료위치(module_exit())가 있다.

  • 아래는 ‘hello, world’를 출력하는 간단한 모듈의 코드이다.

    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/kernel.h>
    static int hello_init(void) {
    printk(KERN_ALERT, "hello\n");
    return 0;
    }
    static void hello_exit(void) {
    printk(KERN_ALERT, "world\n");
    }
    module_init(hello_init); // 모듈 진입점
    module_exit(hello_exit); // 모듈 종료점
    MODULE_LICENSE("GPL"); // 저작권 정보
    MODULE_AUTHOR("Embeddedjune"); // 모듈 제작자 정보
    MODULE_DESCRIPTION("Test Hello,world"); // 모듈에 대한 정보

모듈 설치 준비하기

  • 모듈 작성을 완료했다면, 모듈 소스를 패치의 형태나 커널 소스 트리에 병합한다.
  • 모듈은 /drivers의 적당한 장치 하위 디렉토리에 디렉토리를 만들고 넣는다.
  • /drivers의 Makefile과 방금 만든 하위 디렉토리 안의 Makefile을 수정한다.
  • make 명령어로 모듈을 컴파일한다.

모듈 설치하기

  • make modules_install 명령을 이용해서 모듈을 설치한다.

모듈 의존성 생성하기

  • depmod 명령어를 이용해서 의존성 정보를 반드시 생성한다.

메모리에 모듈 로드하기

  • insmod로 모듈을 메모리에 추가하고 rmmod로 모듈을 제거한다.
  • modprobe 도구는 의존성 해소, 오류 검사 및 보고 등의 고급 기능들을 제공하므로 사용을 적극 권장한다.

3. 장치 모델

  • 리눅스 커널 2.6 버전의 중요한 새 기능으로 ‘장치 모델(Device model)’이 추가됐다.
  • 장치 모델이 추가된 이유는 ‘전원 관리(Power management) 기능 운용’을 위한 정확한 장치 트리(Device tree, 시스템의 장치 구조를 표현하는 트리)를 제공하기 위해서다.
  • 플래시 드라이브가 어느 컨트롤러에 연결됐는지, 어느 장치가 어느 버스에 연결됐는지 정보를 알려주고, 커널이 전원을 차단할 때 트리의 하위 노드 장치부터 전원을 차단할 수 있도록 도와준다.
  • 이러한 일련의 서비스를 정확하고 효율적으로 제공하기 위해 장치 트리 및 장치 모델이 필요하다.
  • 장치 모델은 kobjects, ksets, ktypes 세 가지 구조체로 표현한다. (모든 구조체는 <linux/kobject.h>에 정의되어있다.)
// https://github.com/torvalds/linux/blob/f2e8a57ee9036c7d5443382b6c3c09b51a92ec7e/include/linux/kobject.h#L64
// 커널 자료구조의 기본적인 객체 속성 제공, sysfs 상의 디렉토리와 같음
struct kobject {
const char *name;
struct list_head entry;
struct kobject *parent;
struct kset *kset;
const struct kobj_type *ktype;
struct kernfs_node *sd; /* sysfs directory entry */
struct kref kref;
unsigned int state_initialized:1;
unsigned int state_in_sysfs:1;
unsigned int state_add_uevent_sent:1;
unsigned int state_remove_uevent_sent:1;
unsigned int uevent_suppress:1;
#ifdef CONFIG_DEBUG_KOBJECT_RELEASE
struct delayed_work release;
#endif
};
...
// https://github.com/torvalds/linux/blob/f2e8a57ee9036c7d5443382b6c3c09b51a92ec7e/include/linux/kobject.h#L168C1-L173C22
// 기능상 관련된 kobject의 집합(연결리스트)
struct kset {
struct list_head list;
spinlock_t list_lock;
struct kobject kobj;
const struct kset_uevent_ops *uevent_ops;
} __randomize_layout;
...
// https://github.com/torvalds/linux/blob/f2e8a57ee9036c7d5443382b6c3c09b51a92ec7e/include/linux/kobject.h#L116C1-L123C3
// 공동 동작을 공유하는 kobject의 집합(연결리스트)
struct kobj_type {
void (*release)(struct kobject *kobj); // `kobjects`의 참조횟수가 0이 될 때 호출되서 C++의 소멸자 역할을 한다.
const struct sysfs_ops *sysfs_ops;
const struct attribute_group **default_groups;
const struct kobj_ns_type_operations *(*child_ns_type)(const struct kobject *kobj);
const void *(*namespace)(const struct kobject *kobj);
void (*get_ownership)(const struct kobject *kobj, kuid_t *uid, kgid_t *gid);
};
...
  • kobjects 구조체는 부모 객체를 멤버 포인터 객체로 가지므로 계층 구조를 가지고 있다.
  • kobjects를 사용하기 위해서는 kobject_create() 함수를 사용한다.

sysfs

sysfs 정의

  • sysfs은 kobject 계층 구조를 보여주는 가상 파일시스템​이다.
  • sysfs는 ​가상 파일을 통해 다양한 커널 하위 시스템의 장치 드라이버에 대한 정보를 제공한다.
  • 리눅스 2.6 커널 이상을 이용하는 모든 시스템은 sysfs를 포함하며 /sys 디렉토리에 마운트되어있다.
  • sysfs에는 block, bus, class, dev, devices, firmware, fs, kernel, module, power 등 최소 10개 디렉토리가 포함되어있다.
  • 이 디렉토리들 중 가장 중요한 두 디렉토리는 class와 devices 디렉토리다.
    • class는 시스템 장치의 상위 개념을 정리된 형태로 보여주고,
    • devices는 시스템 장치의 하위 물리적 장치 연결 정보 관계를 보여준다.
    • 나머지 디렉토리는 devices의 데이터를 단순히 재구성한 것에 불과하다.

sysfs에 kobject에 추가하고 제거하기

struct kobject *kobject_create_and_add(const char *name, struct kobject *parent);
void kobject_del(struct kobject *kobj);
  • kobject_create_and_add()kobject_create() 함수와 kobject_add() 함수를 하나로 합친 함수다.
  • kobject 객체를 생성하고 sysfs에 추가한다.
  • kobject 객체를 제거할 때는 kobject_del() 함수를 사용한다.

sysfs에 파일 추가하기

  • kobject를 sysfs 계층구조에 추가해도 kobject가 가리키는 ‘파일’이 없다면 아무 의미가 없다.
  • kobjects 구조체 속 ktypes 구조체는 아무런 인자가 없어도 기본적인 파일 속성을 제공한다.
    • default_attrs : 이 변수를 설정해서 파일의 이름, 소유자, 속성(쓰기, 읽기, 실행)을 부여한다.
    • sysfs_ops : 파일의 기본적인 동작(읽기(show), 쓰기(store))을 정의한다.
  • 속성을 제거하기 위해서는 sysfs_remove_file() 함수를 이용한다.

참고