프로그래밍/리눅스 시스템

[Linux Kernel] Device Driver : Timer

KimuGamJa 2024. 4. 29. 05:33
  • 동작 확인
    • 모듈을 insmod 한 뒤, 로그를 확인한다.
    • HZ 값이 출력되고 있다.
    • HZ 값은 커널 소스에 정의된 값이다.
      => 커널 컴파일 시 설정파일 .config 에 CONFIG_HZ 로 설정되어 있다.

 

 

[Makefile]

KERNEL_HEADERS=/lib/modules/$(shell uname -r)/build

obj-m += devicedriver.o

PWD := $(CURDIR)

driver:
	make -C $(KERNEL_HEADERS) M=$(PWD) modules

clean:
	make -C $(KERNEL_HEADERS) M=$(PWD) cleancopy

 

 

[ devicedriver.c ]

#include <linux/module.h>
#include <linux/printk.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <linux/timer.h>

#define NOD_NAME "deviceFile"

MODULE_LICENSE("GPL");
static int NOD_MAJOR;
static struct class *cls;
static dev_t dev;

static struct timer_list timer;
static void timer_func(struct timer_list *nextTimer){
        pr_info("OH! (%d)\n", HZ);
        mod_timer(nextTimer, get_jiffies_64() + (5*HZ / 10));
}

static int deviceFile_open(struct inode *inode, struct file *filp){
    pr_info("Open Device\n");
    return 0;
}

static int deviceFile_release(struct inode *inode, struct file *filp){
    pr_info("Close Device\n");
    return 0;
}

static struct file_operations fops = {
    .owner = THIS_MODULE,
    .open = deviceFile_open,
    .release = deviceFile_release,
};

static int __init deviceFile_init(void)
{
    NOD_MAJOR = register_chrdev(NOD_MAJOR, NOD_NAME, &fops);
    if( NOD_MAJOR < 0 ){
        pr_alert("Register File\n");
        return NOD_MAJOR;
    }

    pr_info("Insmod Module\n");

    dev = MKDEV(NOD_MAJOR, 0);
    cls = class_create(NOD_NAME);
    device_create(cls, NULL, dev, NULL, NOD_NAME);

    pr_info("Major number %d\n", NOD_MAJOR);
    pr_info("Device file : /dev/%s\n", NOD_NAME);

        timer_setup(&timer, timer_func, 0);
        timer.expires = get_jiffies_64() + (1*HZ);
        add_timer(&timer);

    return 0;
}

static void __exit deviceFile_exit(void)
{
        del_timer_sync(&timer);
    device_destroy(cls, dev);
    class_destroy(cls);

    unregister_chrdev(NOD_MAJOR, NOD_NAME);
    pr_info("Unload Module\n");
}
module_init(deviceFile_init);
module_exit(deviceFile_exit);copy