Răsfoiți Sursa

自动添加设备号

xuxinyi 1 an în urmă
părinte
comite
41cc4ae244

+ 16 - 1
驱动文件/1/readme.md

@@ -16,4 +16,19 @@
     ![alt text](image-7.png)
     5.卸载模块
         rmmod xx
-    ![alt text](image-8.png)
+    ![alt text](image-8.png)
+
+Unix-based systems expose hardware to user space by means of special files, all created
+in the /dev directory upon device registration with the system. Programs willing to
+access a given device must locate its corresponding device file in /dev and perform the
+appropriate system call on it, which will be redirected to the driver of the underlying
+device associated with that special file. Though system calls redirection is done by an
+operating system, what system calls are supported depends on the type of device and the
+driver implementation.
+
+在基于 Unix 的系统中,硬件设备通过特殊文件的形式暴露给用户空间,
+这些特殊文件在设备注册时创建于 /dev 目录下。程序若想访问某个设备,
+必须找到其对应的设备文件,并对该文件执行适当的系统调用,
+这些调用会被操作系统重定向到与该特殊文件关联的底层设备驱动程序。
+虽然系统调用的重定向是由操作系统完成的,
+但支持哪些系统调用则取决于设备的类型和驱动程序的实现。

+ 1 - 0
驱动文件/2/readme.md

@@ -0,0 +1 @@
+自动加载的字符设备驱动

+ 69 - 0
驱动文件/3/charDevice.c

@@ -0,0 +1,69 @@
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/fs.h>       // 包含 file_operations 和 register_chrdev 函数
+#include <linux/cdev.h>     // 包含 cdev 相关结构和函数
+
+#define DEVICE_NAME "charDevice3"
+
+// 文件操作函数声明
+static int dev_open(struct inode *inode, struct file *file);
+static int dev_release(struct inode *inode, struct file *file);
+static ssize_t dev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos);
+static ssize_t dev_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos);
+
+// 文件操作结构
+static struct file_operations fops = {
+    .owner = THIS_MODULE,
+    .open = dev_open,
+    .release = dev_release,
+    .read = dev_read,
+    .write = dev_write,
+};
+
+// 文件操作函数的实现
+static int dev_open(struct inode *inode, struct file *file) {
+    pr_info("Device opened\n");
+    return 0;
+}
+
+static int dev_release(struct inode *inode, struct file *file) {
+    pr_info("Device closed\n");
+    return 0;
+}
+
+static ssize_t dev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) {
+    pr_info("Reading from device\n");
+    return 0; // 假设返回 0 表示读到文件结尾
+}
+
+static ssize_t dev_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) {
+    pr_info("Writing to device\n");
+    return count; // 返回写入的字节数
+}
+
+static int __init helloworld_init(void) {
+    int retvalue;
+
+    // 注册字符设备,使用主设备号 200
+    retvalue = register_chrdev(200, DEVICE_NAME, &fops);
+    if (retvalue < 0) {
+        pr_err("Failed to register char device\n");
+        return -EIO;
+    }
+
+    pr_info("Hello world initialization!\n");
+    return 0;
+}
+
+static void __exit helloworld_exit(void) {
+    // 注销字符设备驱动
+    unregister_chrdev(200, DEVICE_NAME);
+    pr_info("Hello world exit\n");
+}
+
+module_init(helloworld_init);
+module_exit(helloworld_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("John Madieu <john.madieu@gmail.com>");
+MODULE_DESCRIPTION("Linux kernel module skeleton");

BIN
驱动文件/3/img.png


+ 30 - 0
驱动文件/3/readme.md

@@ -0,0 +1,30 @@
+注册字符驱动。但是不自动挂载。
+lsmod charDevice.ko
+mknod /dev/charDevice3 c 200 0
+cat /dev/charDevice
+![img.png](img.png)
+Linux has always enforced device file identification by a unique identifier, composed of
+two parts, a major and a minor.
+
+enforce 强制
+identification 标识
+a unique identifier 一种唯一标识符
+composed of two parts 由两个部分组成
+a major and a minor 主设备号和次设备号~~~~
+这个是个整形数,由主次设备号组成
+the preceding excerpt 前面的摘录
+excerpt 摘录 英 / ˈeksɜːpt
+
+
+Character device data structure introduction
+字符设备数据结构体介绍
+struct cdev {
+    struct kobject kobj;
+    struct module *owner;
+    const struct file_operations *ops;
+    dev_t dev;
+    [...]
+};
+
+include/linux/kdev_t.h
+![img.png](img.png)

+ 88 - 0
驱动文件/4/charDevice.c

@@ -0,0 +1,88 @@
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/fs.h>       // 包含 file_operations 和 register_chrdev 函数
+#include <linux/cdev.h>     // 包含 cdev 相关结构和函数
+
+#define DEVICE_NAME "charDevice2"
+#define CLASS_NAME "my_char_class2"
+static int majorNumber;                  // 设备号
+static struct class* myCharClass = NULL; // 设备类
+// 文件操作函数声明
+static int dev_open(struct inode *inode, struct file *file);
+static int dev_release(struct inode *inode, struct file *file);
+static ssize_t dev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos);
+static ssize_t dev_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos);
+
+// 文件操作结构
+static struct file_operations fops = {
+    .owner = THIS_MODULE,
+    .open = dev_open,
+    .release = dev_release,
+    .read = dev_read,
+    .write = dev_write,
+};
+
+// 文件操作函数的实现
+static int dev_open(struct inode *inode, struct file *file) {
+    pr_info("Device opened\n");
+    return 0;
+}
+
+static int dev_release(struct inode *inode, struct file *file) {
+    pr_info("Device closed\n");
+    return 0;
+}
+
+static ssize_t dev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) {
+    pr_info("Reading from device\n");
+    return 0; // 假设返回 0 表示读到文件结尾
+}
+
+static ssize_t dev_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) {
+    pr_info("Writing to device\n");
+    return count; // 返回写入的字节数
+}
+
+static int __init helloworld_init(void) {
+    int retvalue;
+
+
+// 自动申请设备号
+    majorNumber = register_chrdev(0, DEVICE_NAME, &fops);
+    if (majorNumber < 0) {
+        printk(KERN_ALERT "my_char_device failed to register a major number\n");
+        return majorNumber;
+    }
+    printk(KERN_INFO "my_char_device: registered correctly with major number %d\n", majorNumber);
+
+    // 创建设备类
+    myCharClass = class_create(THIS_MODULE, CLASS_NAME);
+    if (IS_ERR(myCharClass)) {
+        unregister_chrdev(majorNumber, DEVICE_NAME);
+        printk(KERN_ALERT "Failed to register device class\n");
+        return PTR_ERR(myCharClass);
+    }
+
+    // 创建设备
+    device_create(myCharClass, NULL, MKDEV(majorNumber, 0), NULL, DEVICE_NAME);
+    printk(KERN_INFO "my_char_device: device class created correctly\n");
+
+    pr_info("Hello world initialization!\n");
+    return 0;
+}
+
+static void __exit helloworld_exit(void) {
+    device_destroy(myCharClass, MKDEV(majorNumber, 0)); // 删除设备
+    class_unregister(myCharClass);                       // 取消设备类注册
+    class_destroy(myCharClass);                          // 销毁设备类
+    // 注销字符设备驱动
+    unregister_chrdev(200, DEVICE_NAME);
+    pr_info("Hello world exit\n");
+}
+
+module_init(helloworld_init);
+module_exit(helloworld_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("John Madieu <john.madieu@gmail.com>");
+MODULE_DESCRIPTION("Linux kernel module skeleton");

+ 2 - 1
驱动文件/Makefile

@@ -93,4 +93,5 @@ obj-$(CONFIG_LEDS_TRIGGERS)		+= trigger/
 
 #新增
 obj-y+= newchrled.o
-obj-m+= leds-user-defind.o
+obj-m+= leds-user-defind.o
+obj-m+= charDevice.o