linux2.6内核驱动程序注册函数,linux 2.6内核 字符设备驱动 相关函数

概述

本文介绍linux字符设备注册相关的四个函数:cdev_alloc、cdev_init、cdev_add和cdev_del。这四个函数在文件:fs/char_dev.c中定义,在头文件include/linux/cdev.h中声明。其中cdev_alloc和cdev_init是一对“互斥”函数,以不同的方式完成“相同”的功能:为函数cdev_add做前期准备。

cdev_alloc

504 /**

505  * cdev_alloc() - allocate a cdev structure

506  *

507  * Allocates and returns a cdev structure, or NULL on failure.

508  */

509 struct cdev *cdev_alloc(void)

510 {

511     struct cdev *p = kzalloc(sizeof(struct cdev), GFP_KERNEL);

512     if (p) {

513         p->kobj.ktype = &ktype_cdev_dynamic;

514         INIT_LIST_HEAD(&p->list);

515         kobject_init(&p->kobj);

516     }

517     return p;

518 }

从函数名称和第511行的代码可以看出:这个函数动态申请结构体struct cdev,并对其进行初始化,最后将其指针返回。下面结合cdev_init进行进一步说明。

cdev_init

520 /**

521  * cdev_init() - initialize a cdev structure

522  * @cdev: the structure to initialize

523  * @fops: the file_operations for this device

524  *

525  * Initializes @cdev, remembering @fops, making it ready to add to the

526  * system with cdev_add().

527  */

528 void cdev_init(struct cdev *cdev, const struct file_operations *fops)

529 {

530     memset(cdev, 0, sizeof *cdev);

531     INIT_LIST_HEAD(&cdev->list);

532     cdev->kobj.ktype = &ktype_cdev_default;

533     kobject_init(&cdev->kobj);

534     cdev->ops = fops;

535 }

cdev_alloc和cdev_init的主要区别是:前者动态申请结构体struct cdev并对其进行初始化,后者将通过参数传进来的结构体struct cdev进行初始化。

另一个主要区别是:cdev_alloc函数中没有对struct cdev的ops域进行初始化,需要在cdev_alloc函数调用之后有专门的代码对struct cdev的ops域进行初始化,而cdev_init函数中使用通过参数传进来的struct file_operations结构体指针对struct cdev的ops域进行初始化,所以在函数cdev_init调用之后不需要再对struct cdev的ops域进行初始化。

cdev_add

447 /**

448  * cdev_add() - add a char device to the system

449  * @p: the cdev structure for the device

450  * @dev: the first device number for which this device is responsible

451  * @count: the number of consecutive minor numbers corresponding to this

452  *         device

453  *

454  * cdev_add() adds the device represented by @p to the system, making it

455  * live immediately.  A negative error code is returned on failure.

456  */

457 int cdev_add(struct cdev *p, dev_t dev, unsigned count)

458 {

459     p->dev = dev;

460     p->count = count;

461     return kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p);

462 }

函数cdev_alloc和cdev_init只是(申请)并初始化了(部分)结构体struct cdev,此时,struct cdev和内核还没有任何关系。

函数cdev_add就是将函数cdev_alloc和cdev_init初始化后的struct cdev结构体注册到内核中(第461行),自此内核就可以访问设备了。

cdev_del

本函数和函数cdev_add功能相反,从内核中删除设备。

给出代码:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define MY_MAJOR 250

struct class *my_class;

struct cdev cdev;

dev_t dev;

int hello_open (struct inode *inode,struct file *filp)

{

printk("#########  open  ######\n");

return 0;

}

ssize_t hello_read (struct file *filp, char __user *buf, size_t count,loff_t *f_pos)

{

printk("#########  read  ######\n");

return count;

}

ssize_t hello_write (struct file *filp, const char __user *buf, size_t count,loff_t *f_pos)

{

printk ("#############  write  ############\n");

return count;

}

int hello_release (struct inode *inode, struct file *filp)

{

printk("#########  release  ######\n");

return 0;

}

struct file_operations hello_fops ={

.owner = THIS_MODULE,

.open = hello_open,

.read = hello_read,

.write = hello_write,

.release = hello_release,

};

int __init hello_init(void)

{

int rc;

dev = MKDEV(MY_MAJOR,0);

printk ("Test hello dev\n");

cdev_init(&cdev,&hello_fops);

cdev.owner = THIS_MODULE;

cdev.ops = &hello_fops;

rc = cdev_add(&cdev,dev,1);

if (rc < 0)

{

printk ("register %s char dev error\n","hello_dev");

return -1;

}

my_class = class_create(THIS_MODULE,"hello_class");

if(IS_ERR(my_class))

{

printk ("err:create class\n");

return -1;

}

device_create(my_class, NULL, dev,NULL, "hello_dev");

printk ("#############  init  ############\n");

return 0;

}

void __exit hello_exit(void)

{

cdev_del(&cdev);

device_destroy(my_class,dev);

class_destroy(my_class);

printk("#############  exit  ############\n");

}

MODULE_LICENSE("GPL"); module_init(hello_init); module_exit(hello_exit);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值