Linux驱动_globalmem实验
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验(第二章字符设备驱动)
实验一、globalmem 字符设备驱动程序设计
1.实验目的
通过编译一个globalmem字符设备驱动程序并测试,让学员掌握Linux内核简单字符设备驱动的编写、编译、加载、调试过程。
2.实验内容
编写一个简单的内核字符设备驱动程序globalmem.c,实现字符设备的读写操作。用测试程序测试。并为测试程序编写Makefile
3.实验步骤
3.1 添加驱动程序到内核中
Linux 2.6内核的配置系统由以下3个部分组成。
✓Makefile:分布在Linux内核源代码中的Makefile,定义Linux内核的编译规则。
✓配置文件(Kconfig):给用户提供配置选择的功能。
✓配置工具:包括配置命令解释器(对配置脚本中使用的配置命令进行解释)和配置用户界面(提供字符界面和图形界面)。这些配置工具都是使用脚本语言编写的,如Tcl/TK、Perl等。
在Linux内核中增加程序需要完成以下3项工作。
✓将编写的源代码复制到Linux内核源代码的相应目录。
✓在目录的Kconfig文件中增加新源代码对应项目的编译配置选项。
✓在目录的Makefile文件中增加对新源代码的编译条目。
下面就以添加globalmem.c简单字符设备驱动为例,讲解如何在内核源代码drivers目录下为为自己的驱动添加目录:
3.1.1修改目录~/drivers/char/下的Kconfig文件,在100行处添加如下内容
config GLOBALMEM
tristate “MY Globalmem Dri v ers”
depends on MACH_MINI2440
default m if MACH_MINI2440
help
“this is myself globalmem driver”
3.1.2修改目录~/drivers/char/下的Makefile文件,在115行处添加如下内容
obj-$(CONFIG_GLOBALMEM) +=globalmem.o
3.1.3 在目录文件~/drivers/char/下添加文件globalmem.c,具体内容如下:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define GLOBALMEM_SIZE 0x1000 /*全局内存最大4K字节*/
#define MEM_CLEAR 0x1 /*清0全局内存*/
#define GLOBALMEM_MAJOR 244 /*预设的globalmem的主设备号*/
MODULE_LICENSE("Dual BSD/GPL");
static int globalmem_major = GLOBALMEM_MAJOR;
/*globalmem设备结构体*/
struct globalmem_dev
{
struct cdev cdev; /*cdev结构体*/
unsigned char mem[GLOBALMEM_SIZE]; /*全局内存*/
};
struct globalmem_dev *globalmem_devp; /*设备结构体指针*/
/*文件打开函数*/
int globalmem_open(struct inode *inode, struct file *filp)
{
/*将设备结构体指针赋值给文件私有数据指针*/
filp->private_data = globalmem_devp;
return 0;
}
/*文件释放函数*/
int globalmem_release(struct inode *inode, struct file *filp)
{
return 0;
}
/* ioctl设备控制函数 */
static int globalmem_ioctl(struct inode *inodep, struct file *filp, unsigned
int cmd, unsigned long arg)
{
struct globalmem_dev *dev = filp->private_data;/*获得设备结构体指针*/
switch (cmd)
{
case MEM_CLEAR:
memset(dev->mem, 0, GLOBALMEM_SIZE);
printk(KERN_INFO "globalmem is set to zero\n");
break;
default:
return - EINVAL;
}
return 0;
}
/*读函数*/
static ssize_t globalmem_read(struct file *filp, char __user *buf, size_t size,loff_t *ppos)
{
unsigned long p = *ppos;
unsigned int count = size;
int ret = 0;
struct globalmem_dev *dev = filp->private_data; /*获得设备结构体指针*/
/*分析和获取有效的写长度*/
if (p >= GLOBALMEM_SIZE)
return count ? - ENXIO: 0;
if (count > GLOBALMEM_SIZE - p)
count = GLOBALMEM_SIZE - p;
/*内核空间->用户空间*/
if (copy_to_user(buf, (void*)(dev->mem + p), count))
{
ret = - EFAULT;
}
else
{
*ppos += count;
ret = count;
printk(KERN_INFO "read %d bytes(s) from %d\n", count, p);
}
return ret;
}
/*写函数*/
static ssize_t globalmem_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos)
{
unsigned long p = *ppos;
unsigned int count = size;
int ret = 0;
struct globalmem_dev *dev = filp->private_data; /*获得设备结构体指针*/
/*分析和获取有效的写长度*/
if (p >= GLOBALMEM_SIZE)
return count ? - ENXIO: 0;
if (count > GLOBALMEM_SIZE - p)
count = GLOBALMEM_SIZE - p;
/*用户空间->内核空间*/
if (copy_from_user(dev->mem + p, buf, count))
ret = - EFAULT;