- 论坛徽章:
- 0
|
一. cdev结构体:
struct cdev
{
Struct kobject kobj; //内嵌的kobject对象
Struct module *owner; //所属模块
Struct file_operations *ops; //文件操作结构体
Struct list_head list;
Dev_t dev; //设备号
Unsigned int count;
}
二. 使用下列宏可以从 dev_t获得主设备号和次设备号
MAJOR(dev_t dev)
MINOR(dev_t dev)
三. 使用下列宏则可以通过主设备号和设备号生成dev_t
MKDEV(int major, int minor)
四. LINUX2.6内核提供了一组函数用于操作cdev结构体:
Void cdev_init(struct cdev *, struct file_operations *); //初始化cdev成员
Struct cdev *cdev_alloc(void); //动态申请一个cdev内存
Void cdev_put(struct cdev *p);
Int cdev_add(struct cdev *,dev_t, unsigned); //向系统添加一个cdev
Void cdev_del(struct cdev *); //向系统删除一个cdev
五. 分配和释放设备号
1. int register_chrdev_region(dev_t from, unsigned count, const char *name); //申请设备号
2. void unregister_chrdev_region(dev_t from, unsigned count); //释放设备号
六. globalmem设备驱动
1. 头文件.宏及设备结构体
#include
#include
#include
#include
#include
#include
#include
#include
#define GLOBALMEM_SIZE 0x1000 //全局内存大小
#define MEM_CLEAR 0x1 //清零全局内存
#define GLOBALMEM_MAJOR 254 //预设的globalmem的主设备号
static globalmem_major = GLOBALMEM_MAJOR;
struct globalmem_dev
{
struct cdev cdev;
unsigned char mem[GLOBALMEM_SIZE];
}
struct globalmem_dev dev; //设备结构体实例
2. 加载设备驱动:
static void globalmem_setup_cdev()
{
int err, devno = MKDEV(globalmem_major, 0);
cdev_init(&dev.cdev, &globalmem_fops);
dev.cdev.owner = THIS_MODULE;
dev.cdev.ops = &globalmem_fops;
err = cdev_add(&dev.cdev, devno, 1);
if (err)
printk(KERN_NOTICE "Error %d adding globalmem", err);
}
int globalmem_init(void)
{
int result;
dev_t devno = MKDEV(globalmem_major, 0);
if(globalmem_major) {
result = register_chrdev_region(devno, 1, "globalmem");
} else {
result = alloc_chrdev_region(&devno, 0, 1, "globalmem");
globalmem_major = MAJOR(devno);
}
if(result
return result;
globalmem_setup_cdev();
return 0;
}
3. 卸载设备驱动:
void globalmem_exit(void)
{
cdev_del(&dev.cdev);
unregister_chrdev_region(MKDEV(globalmem_major, 0), 1);
}
4. file_operations结构体:
static const struct file_operations globalmem_fops =
{
.owner = THIS_MODULE,
.llseek = globalmem_llseek,
.read = globalmem_read,
.write = globalmem_wirte,
.ioctl = gloalmem_ioctl,
};
5. 读函数:
static ssize_t globalmem_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
{
unsigned long p = *ppos;
int ret = 0;
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;
prink(KERN_INFO "read %d butes(s) from %d\n", count, p);
}
return ret;
}
6. 写函数:
static ssize_t globalmem_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos)
{
unsigned long p = *ppos;
int ret =0;
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;
} else {
*ppos += count;
ret = count;
prink(KERN_INFO "written %d butes(s) from %d\n", count, p);
}
return ret;
}
7. seek函数
static loff_t globalmem_llseek(struct file *filp, loff_t offset, int orig)
{
loff_t ret;
switch(orig)
{
case 0:
if (offset
ret = -EINVAL;
break;
}
if ((unsigned int)offset > GLOBALMEM_SIZE) {
ret = - EINVAL;
break;
}
filp->f_pos = (unsigned int) offset;
ret = file->f_pos;
%
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/93882/showart_1899900.html |
|