linux内核中版本信息字符串为一宏定义,如下:
1 | #define version(a) Version_ ## a |
在u-boot中,同样有相似的宏定义:
1 | #define XMK_STR(x) #x |
它是这样使用的(例子还有很多):
1 | "baudrate=" MK_STR(CONFIG_BAUDRATE) "\0" |
作一测试,语句和运行结果如下:
1 | printf("XMK_STR(x):%s \nMK_STR(x): %s\n", XMK_STR(CONFIG_BAUDRATE), MK_STR(CONFIG_BAUDRATE)); |
一开始我不明白为何要定义两个宏(XMK_STR和MK_STR),经过测试才知道原因。因为在实际使用过程中,宏括号里的也是宏定义,如果单单使用XMK_STR,即C语言中的“#”,则会原封不动地输出“#”后的内容(亦即宏括号里的内容),如果这个“参数”也是宏的话,输出的当然是这个宏的名称了,正如上面所示那样。所以为了输出宏的真正内容使用,需要再加上一个宏,不过此刻的内容是一个字符串。
在u-boot中使用nand write.yaffs2命令将根文件系统映像写入nand flash中,会有如下提示:
1 | Writing at 0x3680000 --55% is complete |
变化的是其中的地址(偏移量)和进度(百分之几)。像这个其实不难实现。在实际代码中是这样的:
1 | printf("\rWriting at 0x%llx --%d%% is complete",offset,100-(left_to_write/(*length/100))); |
关键的便是其中的“r”,ASCII码为0x0d,这个字符我们很常见,在区别和处理Windows和Linux的回车换行时经常遇到。它就是“回车”,回到一行的行首。而C语言的printf函数常用的“n”则是换行,ASCII码为0x0a。这里不能使用“n”,否则会影响显示效果。
上面的语句每执行一次,那一行字符串都重新回到这一行的行首。这样看上去只有地址和进度来变化,其实整个字符串都已经重新打印一遍了,只不过我们没这个感觉而已。 大家可以测试一下下面的语句:
1 | for (i = 0; i < 100; i++) |
大家可以测试一下“\r”和“\n”这些组合的效果。 木草山人 即日