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

设备管理 – Linux内核API device_initialize

函数device_initialize()对新创建的逻辑设备对象进行部分字段的初始化工作,主要完成设备引用计数器、信号量、设备访问锁等字段的初始化工作。

device_initialize文件包含

#include <linux/device.h>

device_initialize函数定义

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

函数定义格式:

void device_initialize(struct device *dev)

device_initialize输入参数说明

  • 函数的输入参数是struct device结构体类型的指针变量,代表即将被初始化的逻辑设备,此结构体的定义在本教程函数device_create()说明部分已详细说明。

device_initialize返回参数说明

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

device_initialize实例解析

实例说明:此实例不是简单地说明函数device_initialize()、device_add()、device_del()的作用,而是编写一个完整的字符设备驱动程序,在驱动程序中说明函数的作用,并体现函数的用处。

编写测试文件:device_initialize_add_del.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 class *mem_class;            //设备类指针
struct device *dev;                 //逻辑设备类指针
static int  __init  device_initialize_add_del_init(void);       //模块加载函数声明
static void  __exit device_initialize_add_del_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_initialize_add_del_init(void)
{
int res;
printk("into device_initialize_add_del_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);               //为逻辑设备开辟内存空间
device_initialize(dev);                               //初始化新创建的逻辑设备
printk("device initialize success\n");
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_add(dev);       //将新创建的逻辑设备加入Linux内核系统
if(res)
{
printk("device add failed\n");
device_del(dev);                                  //失败,则删除逻辑设备
kfree(dev);                                       //失败,释放逻辑设备的内存空间
return -1;
}
printk("add device success\n");
printk("out device_initialize_add_del_init\n");
return 0;
}

模块退出函数定义:

void __exit device_initialize_add_del_exit (void)
{
printk("into device_initialize_add_del_exit\n");
unregister_chrdev(MEM_MAJOR, "my_char_dev");     //注销字符设备
if(dev)
{
device_del(dev);         //删除逻辑设备
}
printk("device del 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_initialize_add_del_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;
}
/*逻辑设备释放处理函数*/
static void device_register_release(struct device *dev)
{
pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
kfree(dev);                                      //释放设备占用的内存空间
}

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

module_init(device_initialize_add_del_init);    //模块加载
module_exit(device_initialize_add_del_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_initialize_add_del.ko插入内核模块,然后输入命令dmesg -c查看模块插入结果,会出现如图A所示的结果。

Linux内核API device_initialize

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

Linux内核API device_initialize

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

Linux内核API device_initialize

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

Linux内核API device_initialize

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

Linux内核API device_initialize

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

Linux内核API device_initialize

结果分析:

由图A~图C可以看出设备驱动的添加成功,逻辑设备目录及设备文件的创建都成功,说明函数device_initialize()和函数device_add()是成功执行的。图D是用户态的测试程序显示的结果,与图E进行对比可以说明设备驱动程序的添加是成功的。图F是模块卸载之后的显示结果,当命令rmmod device_initialize_add_del.ko执行之后,重新执行命令ls /dev和命令ls /sys/devices/virtual/my_char_dev,可以看出不会出现和图B、图C相同的结果,/dev目录下的设备文件my_char_dev会消失,/sys/devices/virtual/my_char_dev/目录下的目录my_char_dev也会消失。

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

Java基础教程Android基础教程