uboot----getenv_IPaddr代码解析

来源:互联网 发布:java多线程socket队列 编辑:程序博客网 时间:2024/06/11 11:26

                  这几天看uboot,感觉getenv函数里嵌套了很多其他函数,一直没搞清是怎么实现get的。今天终于领会了,把它记下来,供大家一起学习。

                我研究的是IPaddr的环境变量如何get的,其实就是 gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");该如何分析。先找到getenv_IPaddr函数:

typedef ulong  IPaddr_t;
IPaddr_t getenv_IPaddr (char *var){ return (string_to_ip(getenv(var)));

                getenv_IPaddr函数使用字符串"ipaddr"做为参数,返回一个ulong型整数。再看getenv函数:

char *getenv (char *name){int i, nxt;WATCHDOG_RESET();for (i=0; env_get_char(i) != '\0'; i=nxt+1) {int val;for (nxt=i; env_get_char(nxt) != '\0'; ++nxt) {if (nxt >= CFG_ENV_SIZE) {return (NULL);}}if ((val=envmatch((uchar *)name, i)) < 0)continue;return ((char *)env_get_addr(val));}return (NULL);}

          getenv 是一个指针函数,返回字符型指针。为什么会返回字符型指针?后面再说。getenv 函数的参数是字符指针变量name,实参就是“ipaddr"。从这里开始出现了一大堆莫名其妙的函数env_get_char,envmatch,env_get_addr。在分析getenv 之前,还得先把这些其他的函数搞清楚。首先看env_get_char:

uchar (*env_get_char)(int) = env_get_char_init;
static uchar env_get_char_init (int index){uchar c;/* if crc was bad, use the default environment */if (gd->env_valid){c = env_get_char_spec(index);} else {c = default_environment[index]; //返回default_environment指定位置的字符}return (c);}

        env_get_char和env_get_char_init等效,参数为int,返回default_environment指定位置的字符。default_environment是定义了一系列缺省的环境变量值。以IP地址为例

#ifdefCONFIG_IPADDR"ipaddr="MK_STR(CONFIG_IPADDR)"\0"#endif
#define CONFIG_IPADDR192.168.1.230

结果是  "ipaddr=192.168.1.230”+"\0"

再看envmatch:

static intenvmatch (uchar *s1, int i2){while (*s1 == env_get_char(i2++))if (*s1++ == '=')return(i2);if (*s1 == '\0' && env_get_char(i2-1) == '=')return(i2);return(-1);}

           我开始一直搞不清envmatch 是如何比较的。现在搞清楚了,它是在比较“ipaddr"和"ipaddr=192.168.1.230”。while (*s1 == env_get_char(i2++)) 就是从default_environment字符串的指定位置开始比较,指定位置由env_get_char返回值所定,比较不一致时函数返回-1。当比较到default_environment字符串的IPaddr时,开始有相同的字符出现了,这时while值为1,依次比较i,p,a,d,d,r字符,因为每比较一次,S1(“ipaddr")和i2的值都加1,即指向下一个字符。当比较完"r"后,指针指向了下一个字符即"=", "="之后的字符串正是我们需要的,所以return(i2),i2是赋给val的,下一步就是env_get_addr(val)。

uchar *env_get_addr (int index){if (gd->env_valid) {return ( ((uchar *)(gd->env_addr + index)) );} else {return (&default_environment[index]);}}

             找到了val的值,也就是ipaddr在default_environment中所处的位置,即可以返回ipaddr字符串的地址。前面说为什么会返回字符型指针?这里给出了答案。注意:这里返回的是指针,是192.168.1.230的地址,确切地说是"1"的指针地址。

             我们再返回char *getenv (char *name) 函数,其返回值也就192.168.1.230的地址, 这个地址是string_to_ip函数的地址。

IPaddr_t string_to_ip(char *s){IPaddr_t addr;char *e;int i;if (s == NULL)return(0);for (addr=0, i=0; i<4; ++i) {ulong val = s ? simple_strtoul(s, &e, 10) : 0;addr <<= 8;addr |= (val & 0xFF);if (s) {s = (*e) ? e+1 : e;}}return (htonl(addr));}

        string_to_ip函数将字符串192.168.1.230转化成整数,关键的地方是for (addr=0, i=0; i<4; ++i),这里可以看出进行了四次转化,分别是四个段。但是函数simple_strtoul是如何区分"."而分成四个段? 这是靠simple_strtoul中的while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) ? toupper(*cp) : *cp)-'A'+10) < base)实现的,因为当while遇到"."时,判定条件即为0,就不再判定而往下走了。四个段都操作完成,就出现了addr = (((((192 << 8) | 168) << 8) | 1) << 8 ) | 230,

        

           


         

 

 

 

 

 

0 0
原创粉丝点击