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

设备管理 – Linux内核API device_rename

函数device_rename()用于给已存在的逻辑设备重新命名,将逻辑设备的名字更新为此函数的第二个参数所代表的字符串,并重命名目录/sys/devices/virtual/下此逻辑设备对应的设备文件夹名。

如果内核中有宏CONFIG_SYSFS_DEPRECATED的定义,则此函数也能够更新此逻辑设备对应的设备类的名字,并重命名目录/dev下对应的设备文件名。

device_rename文件包含

#include <linux/device.h>

device_rename函数定义

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

函数定义格式:

int device_rename(struct device *dev, char *new_name)

device_rename输入参数说明

  • 函数 device_rename() 的第一个参数是struct device结构体类型的指针,代表即将被重命名的逻辑设备,此结构体在本教程函数

    device_create()的说明文档中已详细说明。

  • 第二个输入参数代表逻辑设备的新设备名,用于替换逻辑设备的设备名。

device_rename返回参数说明

  • 此函数的返回值是int型的变量,可能的取值是0、-EINVAL、-ENOMEM,其中EINVAL的值为22, ENOMEM的值为12。

device_rename实例解析

编写测试文件:device_rename.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>
#include <linux/kobject.h>
MODULE_LICENSE("GPL");
#define MEM_MALLOC_SIZE    4096              //缓冲区大小
#define MEM_MAJOR       245                  //主设备号
#define MEM_MINOR          0                 //次设备号
char *mem_spvm;                             //缓冲区指针,指向内存区
struct class *mem_class;                    //设备类指针
struct device *dev;                         //逻辑设备指针
static int  __init  device_rename_init(void);                   //模块加载函数声明
static void  __exit device_rename_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);
static void device_register_release(struct device *dev);      //逻辑设备释放处理函数
/*定义设备驱动文件结构体*/
struct file_operations mem_fops =
{
.owner=THIS_MODULE,                    //结构体拥有者初始化
.open = mem_open,                      //设备打开函数
.release = mem_release,                //设备关闭函数
.read = mem_read,                      //设备读函数
.write = mem_write,                    //设备写函数
};

模块加载函数定义:

int __init device_rename_init(void)
{
int res;
printk("into device_rename_init\n");
mem_spvm = (char *)vmalloc(MEM_MALLOC_SIZE);                    //开辟内存缓冲区
res=register_chrdev(MEM_MAJOR, "my_char_dev", &mem_fops); //注册字符设备
if(res)                                                          //注册失败
{
unregister_chrdev(MEM_MAJOR, "my_char_dev");                 //删除字符设备
printk("register char dev failed\n");
return -1;
}
printk("register char dev success\n");
mem_class = class_create(THIS_MODULE, "my_char_dev");        //创建设备类
if(IS_ERR(mem_class))                                        //判断创建是否成功
{
printk("failed in creating class.\n");
class_destroy(mem_class);                            //失败,则销毁设备类
return -1;
}
printk("class create success\n");
dev=kzalloc(sizeof(*dev), GFP_KERNEL);                      //为逻辑设备开辟内存空间
/*初始化设备的设备号,包括主设备号和次设备号*/
dev->devt=MKDEV(MEM_MAJOR, MEM_MINOR);
dev->class=mem_class;                                       //初始化设备类
dev->release = device_register_release;                     //初始化设备注销处理函数
res= kobject_set_name(&dev->kobj, "my_char_dev");           //初始化设备引用计数器
if(res)
{
printk("kobject_set_name_vargs failed\n");
kfree(dev);                //失败,释放设备占用的内存空间
return -1;
}
res=device_register(dev);      //将逻辑设备加入Linux内核系统
if(res)
{
printk("register device failed\n");
device_unregister(dev);    //注册失败,释放逻辑设备
kfree(dev);                //释放逻辑设备占用的内存空间
return -1;
}
printk("register device success\n");
printk("the name of the device is:%s\n", dev->kobj.name);        //显示逻辑设备名
printk("the name of the class is:%s\n", dev->class->name);       //显示逻辑类名
res=device_rename(dev, "char_dev");                              //重命名逻辑设备
if(res)
{
printk("rename device failed\n");
}
/*显示函数调用之后的逻辑设备名*/
printk("the new name of the device is:%s\n", dev->kobj.name);
/*显示函数调用之后的逻辑类名*/
printk("the new name of the class is:%s\n", dev->class->name);
printk("out device_rename_init\n");
return 0;
}

模块退出函数定义:

void __exit device_rename_exit (void)
{
printk("into device_rename_exit\n");
unregister_chrdev(MEM_MAJOR, "my_char_dev");            //注销字符设备
if(dev)
{
printk("device unregister\n");
device_unregister(dev);                             //删除逻辑设备
}
printk("device unregister success\n");
if(mem_class)
class_destroy(mem_class);                           //删除设备类
printk("class destroy success\n");
if (mem_spvm ! = NULL)
vfree(mem_spvm);                                    //释放内存缓冲区空间
printk("vfree mem_spvm OK\n");
printk("out device_rename_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)
{
printk("in the function mem_read\n");
return 0;
}
/*设备写函数定义,在此没有实际意义,因为不涉及设备的写*/
ssize_t mem_write(struct file *filp, const char *buf, size_t size, loff_t *lofp)
{
printk("in the function mem_write\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;
}
/*逻辑设备释放处理函数*/
static void device_register_release(struct device *dev)
{
pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
kfree(dev);                             //释放设备占用的内存空间
}

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

module_init(device_rename_init);         //模块加载
module_exit(device_rename_exit);         //模块卸载

实例运行结果及分析

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

Linux内核API device_rename

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

Linux内核API device_rename

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

Linux内核API device_rename

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

Linux内核API device_rename

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

Linux内核API device_rename

结果分析:

由图A可以看出逻辑设备被重命名成功,而此逻辑设备对应的逻辑类没有被重命名,说明内核中没有宏CONFIG_SYSFS_DEPRECATED的定义。图B可以说明逻辑类没有被重命名。图C和图D说明函数device_rename()在重命名逻辑设备的同时也会重命名逻辑设备在目录/sys/devices/virtual/my_char_dev/下对应的逻辑设备目录名,而对应的设备目录里面的内容不会更改。

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

Java基础教程Android基础教程