微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 嵌入式Linux设备驱动开发之:实验内容——test驱动

嵌入式Linux设备驱动开发之:实验内容——test驱动

时间:08-13 来源:3721RD 点击:

11.7 实验内容--test驱动

1.实验目的

该实验是编写最简单的字符驱动程序,这里的设备也就是一段内存,实现简单的读写功能,并列出常用格式的Makefile以及驱动的加载和卸载脚本。读者可以熟悉字符设备驱动的整个编写流程。

2.实验内容

该实验要求实现对虚拟设备(一段内存)的打开、关闭、读写的操作,并要通过编写测试程序来测试虚拟设备及其驱动运行是否正常。

3.实验步骤

(1)编写代码。

这个简单的驱动程序的源代码如下所示:

/* test_drv.c */

#include <linux/module.h>

#include <linux/init.h>

#include <linux/fs.h>

#include <linux/kernel.h>

#include <linux/slab.h>

#include <linux/types.h>

#include <linux/errno.h>

#include <linux/cdev.h>

#include <asm/uaccess.h>

#define TEST_DEVICE_NAME "test_dev"

#define BUFF_SZ 1024

/*全局变量*/

static struct cdev test_dev;

unsigned int major =0;

static char *data = NULL;

/*读函数*/

static ssize_t test_read(struct file *file,

char *buf, size_t count, loff_t *f_pos)

{

int len;

if (count < 0 )

{

return -EINVAL;

}

len = strlen(data);

count = (len > count)?count:len;

if (copy_to_user(buf, data, count)) /* 将内核缓冲的数据拷贝到用户空间*/

{

return -EFAULT;

}

return count;

}

/*写函数*/

static ssize_t test_write(struct file *file, const char *buffer,

size_t count, loff_t *f_pos)

{

if(count < 0)

{

return -EINVAL;

}

memset(data, 0, BUFF_SZ);

count = (BUFF_SZ > count)?count:BUFF_SZ;

if (copy_from_user(data, buffer, count)) /* 将用户缓冲的数据复制到内核空间*/

{

return -EFAULT;

}

return count;

}

/*打开函数*/

static int test_open(struct inode *inode, struct file *file)

{

printk("This is open operation\n");

/* 分配并初始化缓冲区*/

data = (char*)kmalloc(sizeof(char) * BUFF_SZ, GFP_KERNEL);

if (!data)

{

return -ENOMEM;

}

memset(data, 0, BUFF_SZ);

return 0;

}

/*关闭函数*/

static int test_release(struct inode *inode,struct file *file)

{

printk("This is release operation\n");

if (data)

{

kfree(data); /* 释放缓冲区*/

data = NULL; /* 防止出现野指针 */

}

return 0;

}

/* 创建、初始化字符设备,并且注册到系统*/

static void test_setup_cdev(struct cdev *dev, int minor,

struct file_operations *fops)

{

int err, devno = MKDEV(major, minor);

cdev_init(dev, fops);

dev->owner = THIS_MODULE;

dev->ops = fops;

err = cdev_add (dev, devno, 1);

if (err)

{

printk (KERN_NOTICE "Error %d adding test %d", err, minor);

}

}

/* 虚拟设备的file_operations结构 */

static struct file_operations test_fops =

{

.owner = THIS_MODULE,

.read = test_read,

.write = test_write,

.open = test_open,

.release = test_release,

};

/*模块注册入口*/

int init_module(void)

{

int result;

dev_t dev = MKDEV(major, 0);

if (major)

{/* 静态注册一个设备,设备号先前指定好,并设定设备名,用cat /proc/devices来查看 */

result = register_chrdev_region(dev, 1, TEST_DEVICE_NAME);

}

else

{

result = alloc_chrdev_region(&dev, 0, 1, TEST_DEVICE_NAME);

}

if (result < 0)

{

printk(KERN_WARNING "Test device: unable to get major %d\n", major);

return result;

}

test_setup_cdev(&test_dev, 0, &test_fops);

printk("The major of the test device is %d\n", major);

return 0;

}

/*卸载模块*/

void cleanup_module(void)

{

cdev_del(&test_dev);

unregister_chrdev_region(MKDEV(major, 0), 1);

printk("Test device uninstalled\n");

}

(2)编译代码。

虚拟设备的驱动程序的Makefile如下所示:

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top