泰山派7--在编写驱动中创建设备节点

本文范例是,在泰山派驱动编写中,用自动创建的方式,创建设备节点。
准备工作:
材料:
- 一台装有Linux虚拟机的PC
- 一个泰山派开发板
- 一个串口烧录器CH341
1
设备节点介绍

在Linux系统中 每个设备都有一个对应的设备文件代表他们,应用程序通过操作这个文件达到操作设备的目的。这些设备文件就是设备节点,一般都创建在dev目录下。每个设备节点都有一个主设备号和一个副设备号,Linux可以通过主设备号找到他对应的file_operation结构体,用副设备号确定设备是同类设备中的第几个。
创建节点有两种方式:1.手动创建。 2.在注册设备时自动创建。
我们一般都用自动创建的方式,今天我们也用自动创建的方式。
2
udev机制







12345
在嵌入式Linux中一般使用mdev(udev的简化版本)机制来实现节点的创建和删除,udev 是一个用户程序它可以根据系统中设备的状态来创建和删除设备节点。大概流程:当设备驱动加载成功时,会在/sys/class/下生成xxx文件夹,udev会根据这个文件夹中的信息,在/dev/下生成xxx设备节点。
那么在驱动编写中主要的任务就是用class_create函数生成/sys/class/下的xxx类文件夹,用device_create函数在xxx文件夹下创建一个设备。在驱动卸载时会用device_destroy函数删掉创建的设备,再用class_destroy函数删掉创建的类。
3
编写代码

代码如下:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/moduleparam.h>
#include <linux/fs.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>
#include <linux/device.h>
static int major=0; //驱动主设备号变量
static int minor=0; //驱动副设备号变量
dev_t dev_num;
struct cdev cdev_test; //设置一个cdev结构体的变量
struct class *class; //设置一个class结构体的指针变量
struct device *device; //设置一个device结构体的指针变量
static int cdev_test_open(struct inode *inode, struct file *file) //自己仿造的open函数
{
printk("this is cdev_test_open\n");
return 0;
}
static ssize_t cdev_test_read(struct file *file, char __user *buf, size_t size, loff_t *off) //自己仿造的read函数
{
printk("this is cdev_test_read\n");
return 0;
}
static ssize_t cdev_test_write(struct file *file, const char __user *buf, size_t size, loff_t *off) //自己仿造的write函数
{
printk("this is cdev_test_write\n");
return 0;
}
static int cdev_test_release(struct inode *inode, struct file *file) //自己仿造的release函数
{
printk("this is cdev_test_release\n");
return 0;
}
static struct file_operations cdev_test_ops = { //文件操作函数--驱动的主要操作部分
.owner = THIS_MODULE,
.open = cdev_test_open,
.read = cdev_test_read,
.write = cdev_test_write,
.release = cdev_test_release};
static int modulecdev_init(void){ //驱动加载函数
int ret;
ret=alloc_chrdev_region(&dev_num,0,1,"alloc_name"); //dong态申请驱动设备号部分
if(ret<0){
printk("alloc_chrdev_region is error\n");
}
printk("alloc_chrdev_region is ok\n");
major = MAJOR(dev_num); //获取驱动主设备号部分
minor = MINOR(dev_num); //获取驱动副设备号部分
printk("major is %d\n", major);
printk("minor is %d\n", minor);
cdev_test.owner = THIS_MODULE;
cdev_init(&cdev_test, &cdev_test_ops);
cdev_add(&cdev_test, dev_num, 1);
class=class_create(THIS_MODULE,"test"); //构建设备文件类
device=device_create(class,NULL,dev_num,NULL,"test"); //构建设备节点函数
return 0;
}
static void modulecdev_exit(void) // 驱动卸载函数
{
unregister_chrdev_region(dev_num, 1); // 删除驱动设备号函数
cdev_del(&cdev_test);
device_destroy(class,dev_num); //删除设备文件类
class_destroy(class); //删除设备节点
printk("bye bye\n");
}
module_init(modulecdev_init); //系统加载驱动框架函数
module_exit(modulecdev_exit); //系统卸载驱动框架函数
MODULE_LICENSE("GPL"); //使用协议信息
MODULE_AUTHOR("lxh"); //作者信息
MODULE_VERSION("V1.0"); //版本信息
file.c
3.34KB
app.c
398B
4
上机测试

测试程序还是上次的程序。
file.ko
224.73KB
a.out
13.01KB










更多相关项目
猜你喜欢
评论/提问(已发布 0 条)

