炫意html5
最早CSS3和HTML5移动技术网站之一

设备管理 – Linux内核API device_destroy

函数device_destroy():用于从Linux内核系统设备驱动程序模型中移除一个设备,并删除/sys/devices/virtual目录下对应的设备目录及/dev目录下对应的设备文件。

device_destroy文件包含

#include <linux/device.h>

device_destroy函数定义

在内核源码中的位置:linux-3.19.3/drivers/base/core.c

函数定义格式:

void device_destroy(struct class *cls, dev_t devt);

device_destroy输入参数说明

  • 函数device_destroy()第一个输入参数是struct class类型的变量,代表与待注销的逻辑设备相关的逻辑类,用于Linux内核系统逻辑设备的查找,此结构体的详细解释请读者参考本教程函数__class_create()分析文档的返回参数说明部分。
  • 第二个参数是逻辑设备的设备号,与第一个参数共同确定一个逻辑设备,关于设备号的解释请读者参考本教程函数cdev_add()分析文档的输入参数说明部分。

device_destroy返回参数说明

  • 函数device_destroy()的返回结果是void类型的变量,即不返回任何值。

device_destroy实例解析

实例说明:此实例不是简单地说明函数device_create()和device_destroy()的作用,而是结合一些与字符设备有关的函数,编写一个字符设备的驱动程序,在驱动程序的编写中说明函数device_create()和device_destroy()的作用。将函数class_create()与函数device_create()相结合,共同完成设备文件及逻辑设备的创建,这样只需加载此模块,不需任何其他的操作,注册的字符设备是立即可用的,设备文件的创建不需要再执行命令mknod。

编写测试文件:device_create_destroy.c

头文件引用、全局变量定义及相关函数声明:

/*头文件引用*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>
#include <linux/types.h>
#include <linux/moduleparam.h>
#include <linux/pci.h>
#include <asm/unistd.h>
#include <linux/device.h>
MODULE_LICENSE("GPL");
/*宏定义及全局变量定义*/
#define MEM_MALLOC_SIZE    4096              //缓冲区大小
#define MEM_MAJOR       245                  //主设备号
#define MEM_MINOR          0                 //次设备号
char *mem_spvm;                             //缓冲区指针,指向内存区
struct cdev *mem_cdev;                      //设备对象指针
struct class *mem_class;                    //设备类指针
static int  __init  device_create_destroy_init(void);            //模块加载函数声明
static void  __exit  device_create_destroy_exit(void);           //模块卸载函数声明
static int mem_open(struct inode *ind, struct file *filp);     //设备打开函数声明
static int mem_release(struct inode *ind, struct file *filp); //设备关闭函数声明
/*设备读函数声明*/
static ssize_t mem_read(struct file *filp, char __user *buf, size_t size, loff_t *fpos);
/*设备写函数声明*/
static ssize_t mem_write(struct file *filp, const char __user *buf, size_t size,loff_t *fpos);
/*定义设备驱动文件结构体*/
struct file_operations mem_fops =
{
.open = mem_open,                        //打开设备函数
.release = mem_release,                  //关闭设备函数
.read = mem_read,                        //读设备数据函数
.write = mem_write,                      //向设备写数据函数
};

模块加载函数定义:

int __init device_create_destroy_init (void)
{
int res;
printk("into the device_create_destroy_init\n");
int devno = MKDEV(MEM_MAJOR, MEM_MINOR);             //创建设备号,主设备号与次设备号
mem_spvm = (char *)vmalloc(MEM_MALLOC_SIZE);        //开辟内存缓冲区
if (mem_spvm == NULL)
printk("vmalloc failed! \n");
else                                                 //显示分配缓冲区内存地址
printk("vmalloc successfully! addr=0x%x\n", (unsigned int)mem_spvm);
mem_cdev = cdev_alloc();                            //动态分配一个新的字符设备对象
if (mem_cdev == NULL)
{
printk("cdev_alloc failed! \n");
return 0;
}
cdev_init(mem_cdev, &mem_fops);                     //初始化字符设备对象
mem_cdev->owner = THIS_MODULE;                      //初始化设备持有者
res = cdev_add(mem_cdev, devno, 1);                 //将字符设备加入内核系统
if (res)                                            //添加失败
{
cdev_del(mem_cdev);                             //删除设备驱动
mem_cdev = NULL;                                //释放缓冲区
printk("cdev_add error\n");
}
else
{
printk("cdev_add ok\n");
}
mem_class = class_create(THIS_MODULE, "my_char_dev");       //创建设备类
/*
struct lock_class_key key;
mem_class=__class_create(THIS_MODULE, "my_char_dev", &key); //创建设备类
*/
if(IS_ERR(mem_class))         //判断创建是否成功
{
printk("Err: failed in creating class.\n");
return -1;
}
device_create(mem_class, NULL, MKDEV(MEM_MAJOR, MEM_MINOR), NULL, "my_char_dev");
// 注册设备文件系统,并建立设备节点
printk("out the device_create_destroy_init\n");
return 0;
}

模块退出函数定义:

void __exit device_create_destroy_exit (void)
{
printk("into device_create_destroy_exit\n");
if (mem_cdev ! = NULL)
cdev_del(mem_cdev);               //从内核中将设备删除
printk("cdev_del ok\n");
/*删除设备节点及目录*/
device_destroy(mem_class, MKDEV(MEM_MAJOR, MEM_MINOR)); class_destroy(mem_class);
// 删除设备类
if (mem_spvm ! = NULL)
vfree(mem_spvm);                   //释放缓冲区空间
printk("vfree ok! \n");
printk("out device_create_destroy_exit\n");
}

相关函数定义:

/*设备打开函数定义*/
int mem_open(struct inode *ind, struct file *filp)
{
printk("open vmalloc space\n");
try_module_get(THIS_MODULE);                  //模块引用计数器自加
printk("open vmalloc space success\n");
return 0;
}
/*设备读函数定义*/
ssize_t mem_read(struct file *filp, char *buf, size_t size, loff_t *lofp)
{
int res = -1;
char *tmp;
printk("copy data to the user space\n");
tmp = mem_spvm;
if (size > MEM_MALLOC_SIZE                    //判断读取数据的大小
size = MEM_MALLOC_SIZE;
if (tmp ! = NULL)
res = copy_to_user(buf, tmp, size);       //将内核输入写入用户空间
if (res == 0)
{
printk("copy data success and the data is:%s\n", tmp);    //显示读取的数据
return size;
}
else
{
printk("copy data fail to the user space\n");
return 0;
}
}
/*设备写函数定义*/
ssize_t mem_write(struct file *filp, const char *buf, size_t size, loff_t *lofp)
{
int res = -1;
char *tmp;
printk("read data from the user space\n");
tmp = mem_spvm;
if (size > MEM_MALLOC_SIZE)                   //判断输入数据的大小
size = MEM_MALLOC_SIZE;
if (tmp ! = NULL)
res = copy_from_user(tmp, buf, size);     //将用户输入数据写入内核空间
if (res == 0)
{
printk("read data success and the data is:%s\n", tmp);    //显示写入的数据
return size;
}
else
{
printk("read data from user space fail\n");
return 0;
}
}
/*设备关闭函数定义*/
int mem_release(struct inode *ind, struct file *filp)
{
printk("close vmalloc space\n");
module_put(THIS_MODULE);                       //模块引用计数器自减
printk("close vmalloc space success\n");
return 0;
}

模块加载、退出函数调用:

module_init(device_create_destroy_init);         //模块加载
module_exit(device_create_destroy_exit);         //模块卸载

用户态测试函数:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <linux/fcntl.h>
int main(int argc, char **argv)
{
int fd, cnt;
char buf[256];
printf("char device testing.\n");
fd = open("/dev/my_char_dev", O_RDWR);           //打开字符设备
if (fd == 0)
{
printf("the char dev file cannot be opened.\n");
return 1;
}
printf("input the data for kernel: ");
scanf("%s", buf);                                //输入数据
cnt = write(fd, buf, 256);                       //将输入数据写入设备
if (cnt == 0)
printf("Write Error! \n");
cnt = read(fd, buf, 256);                        //从设备中读取数据
if (cnt > 0)
printf("read data from kernel is: %s\n", buf);
else
printf("read data error\n");
close(fd);                                       //关闭设备
printf("close the char dev file and test over\n");
return 0;
}

实例运行结果及分析

首先编译模块,执行命令insmod device_create_destroy.ko插入内核模块,然后输入命令dmesg -c查看模块插入结果,会出现如图A所示的结果。

Linux内核API device_destroy

然后执行命令ls /dev查看当前系统的设备文件,出现如图B所示的结果。

Linux内核API device_destroy

执行命令ls -l /sys/devices/virtual/my_char_dev/my_char_dev查看逻辑设备目录,出现如图C所示的结果。

Linux内核API device_destroy

用gcc编译器编译用户驱动测试文件,运行编译之后的可执行文件,出现如图D所示的结果。

Linux内核API device_destroy

用户测试程序执行完之后,输入命令dmesg -c,出现如图E所示的结果。

Linux内核API device_destroy

删除内核模块,执行命令rmmod device_create_destroy.ko,然后输入命令dmesg -c,出现如图F所示的信息。

Linux内核API device_destroy

结果分析:

由图A可以看出内核缓冲区分配成功和字符设备添加成功。由图B可以确定字符设备文件创建成功。由图C可以看出逻辑设备目录创建成功,图B和图C的效果都是函数device_create()执行的结果,图B的设备文件对应逻辑设备的逻辑类,即函数class_create()执行创建的逻辑类。图D说明设备文件的读写操作都成功,说明设备的注册及设备文件的创建都是成功的。图E的显示信息说明设备的操作函数都能正常执行,用户态的数据能写入设备,并且用户可以从设备读取数据。图F说明缓冲区的释放及设备的注销都成功,模块卸载之后,重新执行命令ls /dev和命令ls /sys/devices/virtual/my_char_dev,会发现设备文件my_char_dev和逻辑设备目录my_char_dev都不存在了,说明设备被成功地删除。

炫意HTML5 » 设备管理 – Linux内核API device_destroy

Java基础教程Android基础教程