第三章里面,我們使用mknod創建設備節點,常規操作是在驅動init的時候就創建好,使用class_create和device_create創建。
#include "asm/uaccess.h"
#include "linux/scatterlist.h"
#include "linux/types.h"
#include <linux/mm.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/mman.h>
#include <linux/random.h>
#include <linux/init.h>
#include <linux/raw.h>
#include <linux/tty.h>
#include <linux/capability.h>
#include <linux/ptrace.h>
#include <linux/device.h>
#include <linux/highmem.h>
#include <linux/backing-dev.h>
#include <linux/shmem_fs.h>
#include <linux/splice.h>
#include <linux/pfn.h>
#include <linux/export.h>
#include <linux/io.h>
#include <linux/uio.h>
#include <linux/module.h>#include <linux/uaccess.h>#define DEVICE_NAME "hello_device"
static struct class *hello_class;
static struct device *hello_device;
static int major;
#define hello_buf_size 100
static unsigned char hello_buf[hello_buf_size];//ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
//參數含義依次為 要讀取的文件指針 用戶保存數據的buf 讀取數據大小 文件內容的偏移量
static ssize_t hello_read (struct file * filp, char __user *buf, size_t size, loff_t *offset)
{unsigned long len = size > hello_buf_size ? hello_buf_size : size;unsigned long ret = copy_to_user(buf, hello_buf, len);printk("%s %s %d ret = %ld\n", __FILE__, __FUNCTION__, __LINE__, ret);return len;
}//ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
//參數含義依次為 要寫入的文件指針 用戶要寫入的數據buf 寫入數據大小 文件內容的偏移量
static ssize_t hello_write (struct file *filp, const char __user *buf, size_t size, loff_t *offset)
{unsigned long len = size > hello_buf_size ? hello_buf_size : size;unsigned long ret = copy_from_user(hello_buf, buf, len);printk("%s %s %d ret = %ld\n", __FILE__, __FUNCTION__, __LINE__, ret);return len;
}//int (*open) (struct inode *, struct file *);
//參數含義依次為 文件索引節點 文件指針
static int hello_open (struct inode *node, struct file *filp)
{printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);return 0;
}//int (*release) (struct inode *, struct file *);
//參數含義依次為 文件索引節點 文件指針
static int hello_release (struct inode *node, struct file *filp)
{printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);return 0;
}/*構建file_operations結構體*/
static const struct file_operations hello_fops = {.owner = THIS_MODULE,.read = hello_read,.write = hello_write,.open = hello_open,.release = hello_release,
};/*init函數,實現register_chrdev*/
static int __init hello_init(void)
{//數含義依次為 主設備號,如果為0,內核會自動分配一個可用的。設備名,會在/proc/devices中顯示。 file_operations結構體//注冊成功就返回主設備號major = register_chrdev(0, DEVICE_NAME, &hello_fops);//為這個模塊創建一個名為hello的類 在/sys/class/下會生成hello目錄hello_class = class_create(THIS_MODULE, "hello");if (IS_ERR(hello_class)) {pr_err("failed to allocate class\n");return PTR_ERR(hello_class);}//在/sys/class/hello類下創建一個hello設備,同時在/dev/下創建一個hello節點hello_device = device_create(hello_class, NULL, MKDEV(major, 0), NULL, "hello");if (IS_ERR(hello_device)) {pr_err("failed to allocate device\n");return PTR_ERR(hello_device);}printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);return 0;
}/*exit函數unregister_chrdev*/
static void __exit hello_exit(void)
{//先銷毀設備,后銷毀類device_destroy(hello_class, MKDEV(major, 0));class_destroy(hello_class);unregister_chrdev(major, DEVICE_NAME);printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
}module_init(hello_init);
module_exit(hello_exit);
//遵循GPL協議
MODULE_LICENSE("GPL");
現在insmod驅動后,就會在/dev/下自動生成hello節點(/dev/hello),/sys/class/下生成hello目錄并在hello目錄下生成一個hello設備的信息目錄(/sys/class/hello/hello)