在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.首先我们看宏定义:
- /**
- * kobject_set_name - Set the name of an object
- * @kobj: object.
- * @name: name.
- *
- * If strlen(name) >= KOBJ_NAME_LEN, then use a dynamically allocated
- * string that @kobj->k_name points to. Otherwise, use the static
- * @kobj->name array.
- */
- int kobject_set_name(struct kobject * kobj, const char * fmt, ...)
- {
- int error = 0;
- int limit = KOBJ_NAME_LEN;
- int need;
- va_list args;
- char * name;
根据注释我们知道,我们需要对kobject结构体的kname变量进行赋值,当我们输入的实参的字符串的长度超过了最大的长度时,我们就将采用一个动态的赋值(分配一个合适大小的内存),否则我们就进行静态的赋值。
11:我们得到了2个定义的实参,以及用"..."的不定实参。其中第一个参数是我们要操作的结构体kobject,第二个参数,是我们定义的名字赋值操作时的格式,即字符指针的形式。 14:定义静态名字赋值的最大长度,如果超过这个长度,就需要动态赋值。
16:定义一个va_list,这是个字符指针类型。
- #ifdef _M_ALPHA
- typedef struct {
- char *a0; /* pointer to first homed integer argument */
- int offset; /* byte offset of next parameter */
- } va_list;
- #else
- typedef char * va_list;
- #endif
如上述源码第七行所示。
接下来就是赋值过程:
- /*
- * First, try the static array
- */
- va_start(args,fmt); //设置va_start,获取可变参数列表的第一个参数的地址,fmt是可变参数最左边的参数。
- need = vsnprintf(kobj->name,limit,fmt,args); /*使用vsnprintf,其中的参数依次kobj->name是args可变参数的目的输出,其中limit是输出的最大长度限制,fmt是输出的要求格式。
- 返回值为kobj->name的长度(不包括'\0') */
- va_end(args); //清空va_list可变参数列表
- if (need < limit) //如果输出字符的长度小于最大长度,则静态赋值成功。否则,调用动态赋值方法
- name = kobj->name;
- else {
- /*
- * Need more space? Allocate it and try again
- */
- limit = need + 1;
- name = kmalloc(limit,GFP_KERNEL);//指定固定大小的内存空间用于赋值
- if (!name) {
- error = -ENOMEM;
- goto Done;
- }
- va_start(args,fmt);
- need = vsnprintf(name,limit,fmt,args);
- va_end(args);
- /* Still? Give up. */
- if (need >= limit) {
- kfree(name);
- error = -EFAULT;
- goto Done;
- }
- }
- /* Free the old name, if necessary. */
- if (kobj->k_name && kobj->k_name != kobj->name)
- kfree(kobj->k_name);
- /* Now, set the new name */
- kobj->k_name = name;
- Done:
- return error;
- }
- EXPORT_SYMBOL(kobject_set_name);
阅读(5817) | 评论(0) | 转发(0) |