Chinaunix首页 | 论坛 | 博客
  • 博客访问: 154423
  • 博文数量: 33
  • 博客积分: 97
  • 博客等级: 民兵
  • 技术积分: 237
  • 用 户 组: 普通用户
  • 注册时间: 2012-05-04 14:13
文章分类
文章存档

2012年(33)

分类: LINUX

2012-06-19 21:40:28

在linux设备模型中,遇到这个函数,int kobject_set_name(struct kobject *kobj, const char *format , ...);在内核linux-2.6.10/lib/kobject.c中可以找到了对它的定义,在其中,我们遇到了几个陌生的宏定义,如va_list,va_start,va_end以及vsnprintf(...)函数。为了搞懂对kobject结构中的k_name的如何赋值,我们只要学习这几个宏定义,其他的问题都是迎刃而解的!对他们的学习,网上很多,百度、谷歌下就OK。我们直接分析通过源码分分析,来理解名字的赋值过程:       

1.首先我们看宏定义:

点击(此处)折叠或打开

  1. /**
  2.  *    kobject_set_name - Set the name of an object
  3.  *    @kobj:    object.
  4.  *    @name:    name.
  5.  *
  6.  *    If strlen(name) >= KOBJ_NAME_LEN, then use a dynamically allocated
  7.  *    string that @kobj->k_name points to. Otherwise, use the static
  8.  *    @kobj->name array.
  9.  */

  10. int kobject_set_name(struct kobject * kobj, const char * fmt, ...)
  11. {
  12.     int error = 0;
  13.     int limit = KOBJ_NAME_LEN;
  14.     int need;
  15.     va_list args;
  16.     char * name;

根据注释我们知道,我们需要对kobject结构体的kname变量进行赋值,当我们输入的实参的字符串的长度超过了最大的长度时,我们就将采用一个动态的赋值(分配一个合适大小的内存),否则我们就进行静态的赋值。

11:我们得到了2个定义的实参,以及用"..."的不定实参。其中第一个参数是我们要操作的结构体kobject,第二个参数,是我们定义的名字赋值操作时的格式,即字符指针的形式。                  14:定义静态名字赋值的最大长度,如果超过这个长度,就需要动态赋值。

16:定义一个va_list,这是个字符指针类型。

点击(此处)折叠或打开

  1. #ifdef _M_ALPHA
  2. typedef struct {
  3.         char *a0; /* pointer to first homed integer argument */
  4.         int offset; /* byte offset of next parameter */
  5. } va_list;
  6. #else
  7. typedef char * va_list;
  8. #endif

如上述源码第七行所示。

接下来就是赋值过程:

点击(此处)折叠或打开

  1. /*
  2.      * First, try the static array
  3.      */
  4.     va_start(args,fmt);    //设置va_start,获取可变参数列表的第一个参数的地址,fmt是可变参数最左边的参数。
  5.     need = vsnprintf(kobj->name,limit,fmt,args);    /*使用vsnprintf,其中的参数依次kobj->name是args可变参数的目的输出,其中limit是输出的最大长度限制,fmt是输出的要求格式。
  6.     返回值为kobj->name的长度(不包括'\0'*/
  7.     va_end(args);    //清空va_list可变参数列表
  8.     if (need < limit) //如果输出字符的长度小于最大长度,则静态赋值成功。否则,调用动态赋值方法
  9.         name = kobj->name;
  10.     else {
  11.         /*
  12.          * Need more space? Allocate it and try again
  13.          */
  14.         limit = need + 1;
  15.         name = kmalloc(limit,GFP_KERNEL);//指定固定大小的内存空间用于赋值
  16.         if (!name) {
  17.             error = -ENOMEM;
  18.             goto Done;
  19.         }
  20.         va_start(args,fmt);
  21.         need = vsnprintf(name,limit,fmt,args);
  22.         va_end(args);

  23.         /* Still? Give up. */
  24.         if (need >= limit) {
  25.             kfree(name);    
  26.             error = -EFAULT;
  27.             goto Done;
  28.         }
  29.     }

  30.     /* Free the old name, if necessary. */
  31.     if (kobj->k_name && kobj->k_name != kobj->name)
  32.         kfree(kobj->k_name);

  33.     /* Now, set the new name */
  34.     kobj->k_name = name;
  35.  Done:
  36.     return error;
  37. }

  38. EXPORT_SYMBOL(kobject_set_name);


 



 


                                                     

 

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