Linux驱动_globalmem实验

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 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;

相关文档
最新文档