编写一个内核模块,注册为字符设备

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>

#define DEVICE_NAME "my_char_device"
#define BUFFER_SIZE 256

static int major = 0;
static struct cdev my_cdev;
static char buffer[BUFFER_SIZE];
static int cap = 0;

static ssize_t my_char_device_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) {
    if (copy_from_user(buffer, buf, count)) {
        return -EFAULT;
    }
    buffer[count] = '\0';

    if (cap) {
        int i;
        for (i = 0; i < count; i++) {
            if (buffer[i] >= 'a' && buffer[i] <= 'z') {
                buffer[i] -= 32;
            }
        }
    }

    printk(KERN_INFO "Written: %s\n", buffer);
    return count;
}

static const struct file_operations my_fops = {
  .write = my_char_device_write,
};

static int __init my_char_device_init(void) {
    int err;

    err = alloc_chrdev_region(&major, 0, 1, DEVICE_NAME);
    if (err < 0) {
        printk(KERN_ERR "Failed to allocate major number\n");
        return err;
    }

    cdev_init(&my_cdev, &my_fops);
    my_cdev.owner = THIS_MODULE;

    err = cdev_add(&my_cdev, major, 1);
    if (err) {
        printk(KERN_ERR "Failed to add character device\n");
        unregister_chrdev_region(major, 1);
        return err;
    }

    printk(KERN_INFO "Character device registered successfully\n");
    return 0;
}

static void __exit my_char_device_exit(void) {
    cdev_del(&my_cdev);
    unregister_chrdev_region(major, 1);
    printk(KERN_INFO "Character device unregistered\n");
}

module_param(cap, int, S_IRUGO);

module_init(my_char_device_init);
module_exit(my_char_device_exit);

MODULE_LICENSE("GPL");

 

以下是对上述代码的逐步解释:
 
1. 首先,定义了一些必要的头文件和宏。
2. 定义了一些全局变量,包括主要设备号、字符设备结构、缓冲区和转换标志。
3.  my_char_device_write  函数处理对字符设备的写操作。它将用户空间的数据复制到内核缓冲区,并根据  cap  标志进行大小写转换,然后使用  printk  打印出来。
4.  my_char_device_init  函数在模块加载时执行,进行设备号分配、字符设备初始化和添加等操作。
5.  my_char_device_exit  函数在模块卸载时执行,进行设备删除和设备号释放等操作。
6.  module_param  用于定义模块可以接收的参数。
7.  module_init  和  module_exit  分别指定模块加载和卸载时调用的函数。
8.  MODULE_LICENSE  声明模块的许可证。
 
要编译和使用这个内核模块,您需要适当的内核开发环境和工具。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值