为glmemory字符设备驱动分配大小为GLMEMORY_SIZE(4k)的内存空间:
实现函数有:
glmemory_open 文件打开函数
glmemory_release 文件释放函数
glmemory_read 文件读函数
glmemory_write 文件写函数
glmemory_init 设备驱动模块加载函数
glmemory_exit 模块卸载函数
1.在/drivers/下建立glmemory.c文件:
#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
#define GLMEMORY_SIZE 0x1000 /*全局内存大小4k*/
#define MEM_CLEAR 0x1 /*清零全局内存*/
static int glmemory_major = 0;//GLMEMOERY_MAJOR;自动获取主设备号
/*glmemory设备结构体*/
struct glmemory_dev
{
struct cdev cdev; /*cdev结构体*/
unsigned char mem[GLMEMORY_SIZE]; /*全局内存*/
};
struct glmemory_dev *glmemory_devp; /*设备体指针*/
/*文件打开函数*/
int glmemory_open(struct inode *inode, struct file *filp)
{
/*将设备结构体指针赋值给文件私有数据指针*/
filp -> private_data = glmemory_devp;
return 0;
}
/*文件释放函数*/
int glmemory_release(struct inode *inode, struct file *filp)
{
return 0;
}
/*读函数*/
static ssize_t glmemory_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
{
unsigned long p = *ppos;
int ret = 0;
struct glmemory_dev *dev = filp -> private_data; /*获得设备结构体指针*/
/*分析和获取有效的读长度*/
if (p >= GLMEMORY_SIZE)
{
return count ? - ENXIO: 0;
}
if (count >GLMEMORY_SIZE - p)
{
count = GLMEMORY_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 %ld \n",count, p);
}
return ret;
}
/*写函数*/
static ssize_t glmemory_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos)
{
unsigned long p = *ppos;
int ret = 0;
struct glmemory_dev *dev = filp -> private_data; /*获得设备结构体指针*/
/*分析和获取有效的写长度*/
if (p >= GLMEMORY_SIZE)
{
return count ? - ENXIO : 0;
}
if (count >GLMEMORY_SIZE -p)
{
count = GLMEMORY_SIZE - p;
}
/*用户空间————内核空间*/
if (copy_from_user(dev -> mem + p, buf, count))
{
ret = -EFAULT;
}
else
{
*ppos += count;
ret = count;
printk(KERN_INFO "written %d bytes(s) from %ld \n",count , p);
}
return ret ;
}
static const struct file_operations glmemory_fops ={
.owner = THIS_MODULE,
// .llseek = glmemory_llseek,
.read = glmemory_read,
.write = glmemory_write,
// .ioctl = glmemory_ioctl,
.open = glmemory_open,
.release = glmemory_release,
};
/*初始化并添加cdev结构体*/
static void glmemory_setup_cdev(struct glmemory_dev *dev, int index)
{
int err, devno = MKDEV(glmemory_major, index);
cdev_init(&dev->cdev, &glmemory_fops);
dev->cdev.owner = THIS_MODULE;
dev->cdev.ops = &glmemory_fops;
err = cdev_add(&dev->cdev, devno, 1);
if (err)
{
printk(KERN_NOTICE "Error %d adding glmemory %d ", err, index);
}
}
/*设备驱动模块加载函数*/
int glmemory_init(void)
{
int result;
dev_t devno = MKDEV(glmemory_major, 0);
/*申请设备号*/
if (glmemory_major)
result = register_chrdev_region(devno, 1, "glmemory");
else
/*动态获得主设备号*/
{
result = alloc_chrdev_region(&devno, 0, 1, "glmemory");
glmemory_major = MAJOR(devno);
}
if (result < 0)
return result;
/*动态申请设备结构体的内存*/
glmemory_devp = kmalloc(sizeof(struct glmemory_dev), GFP_KERNEL);
if (!glmemory_devp) /*申请失败*/
{
result = -ENOMEM;
goto fail_malloc;
}
memset(glmemory_devp, 0, sizeof(struct glmemory_dev));
glmemory_setup_cdev(glmemory_devp, 0);
return 0;
fail_malloc: unregister_chrdev_region(devno, 1);
return result;
}
/*设备驱动模块卸载函数*/
void glmemory_exit(void)
{
cdev_del(&glmemory_devp->cdev); /*删除cdev结构*/
kfree(glmemory_devp); /*释放设备结构体内存*/
unregister_chrdev_region(MKDEV(glmemory_major, 0), 1); /*释放设备号*/
}
MODULE_AUTHOR("Song Baohua");
MODULE_LICENSE("Dual BSD/GPL");
module_param(glmemory_major, int, S_IRUGO);
module_init(glmemory_init);
module_exit(glmemory_exit);
2.在/drivers/下建立Makefile文件:
obj-m :=glmemory.o
KERNELDIR :=/lib/modules/$(shell uname -r)/build
PWD :=$(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
3.在drivers下执行make(以上代码检查过无错误)
XXX@ubuntu:~/linux/linux-kernel/drivers/glmemory$ make
3. XXX@ubuntu:~/linux/linux-kernel/drivers/glmemory$ sudo insmod glmemory.ko
4. XXX@ubuntu:~/linux/linux-kernel/drivers/glmemory$ rmmod glmemory