Chinaunix首页 | 论坛 | 博客
  • 博客访问: 68163
  • 博文数量: 14
  • 博客积分: 1410
  • 博客等级: 上尉
  • 技术积分: 170
  • 用 户 组: 普通用户
  • 注册时间: 2009-03-20 10:58
文章分类
文章存档

2010年(5)

2009年(9)

我的朋友

分类: 嵌入式

2009-11-14 17:16:34

字符设备的注册
 
   前些时间看了些关于字符设备的资料,当时由于在做别的项目就没去看程序代码和实际去运行代码,发现看理论既晦涩难懂也浪费时间。因此以后再学习新理论知识时,首先要做的就是将理论与实践相结合啊!还是邓爷爷有远见啊!
 
   在内核调用设备操作之前,必须分配并注册一个或多个 struct cdev 结构。
linux/fs.h  中定义了inode结构,在这个结构中有:
     struct cdev *i_cdev  //内核中字符设备的内部结构

注意:只要cdev_add返回了,设备的操作就会被内核调用。因此调用cdev_add之前,应现准备好处理设备上的操作。
 
以下是字符设备的注册过程:
 
  • 为struct cdev 分配空间

struct cdev *my_cdev = cdev_alloc();// 下例中cdev结构被嵌入到scull_dev中,因此此步省略

  • 初始化已分配到得结构:

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

  • 初始化struct cdev 一个所有者字段

dev->cdev.owner = THIS_MODULE;

  • 告知内核struct cdev 结构的信息

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

字符设备的移除:

void cdev_del(struct cdev *p)

example:

struct scull_dev {
 struct scull_qset *data;  /* Pointer to first quantum set */
 int quantum;              /* the current quantum size */
 int qset;                 /* the current array size */
 unsigned long size;       /* amount of data stored here */
 unsigned int access_key;  /* used by sculluid and scullpriv */
 struct semaphore sem;     /* mutual exclusion semaphore     */
 struct cdev cdev;   /* Char device structure  */
};  // 此cdev结构被嵌入到scull_dev中,因此须调用cdev_init来执行该结构的初始化。

int scull_init_module(void) //模块初始化函数
{

.........

   scull_devices = kmalloc(scull_nr_devs * sizeof(struct scull_dev),   GFP_KERNEL);//kmalloc 头文件linux/slab.h  成功返回内存指针 失败:NULL


  if (!scull_devices) {
  result = -ENOMEM;
  goto fail;  /* Make this more graceful */
 }
 memset(scull_devices, 0, scull_nr_devs * sizeof(struct scull_dev));

for (i = 0; i < scull_nr_devs; i++) {
  scull_devices[i].quantum = scull_quantum;
  scull_devices[i].qset = scull_qset;
  init_MUTEX(&scull_devices[i].sem);
  scull_setup_cdev(&scull_devices[i], i);//字符设备的注册
 }
........

}

static void scull_setup_cdev(struct scull_dev *dev, int index)
{
 int err, devno = MKDEV(scull_major, scull_minor + index);
   
 cdev_init(&dev->cdev, &scull_fops);//初始化结构
 dev->cdev.owner = THIS_MODULE; //初始化结构的所有者字段
 dev->cdev.ops = &scull_fops; 
 err = cdev_add (&dev->cdev, devno, 1);//告知内核该结构信息
 /* Fail gracefully if need be */
 if (err)
  printk(KERN_NOTICE "Error %d adding scull%d", err, index);
}

 

void scull_cleanup_module(void) //模块清除函数
{
 int i;
 dev_t devno = MKDEV(scull_major, scull_minor);

 /* Get rid of our char dev entries */
 if (scull_devices) {
  for (i = 0; i < scull_nr_devs; i++) {
   scull_trim(scull_devices + i);
   cdev_del(&scull_devices[i].cdev);//先移除字符设备
  }
  kfree(scull_devices);//在释放内存
 }

#ifdef SCULL_DEBUG /* use proc only if debugging */
 scull_remove_proc();
#endif

 /* cleanup_module is never called if registering failed */
 unregister_chrdev_region(devno, scull_nr_devs);

 /* and call the cleanup functions for friend devices */
 scull_p_cleanup();
 scull_access_cleanup();

}


 

 
  
 
 
 
 
 
 
阅读(1059) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~