话说今天做了一个课程实验,但是出了一点点问题,问题在于突然printf出现无法正常输出了..经过一翻小研究,发现了导致printf不正常的代码...但是不懂这段代码对应的那段软中断处理代码具体做了什么..所以没有继续研究下去..今天记录在此,希望在不久的将来能够查明是什么原因...
/* 一个让printf不正常工作的例子 */ /* 如果程序使用下面的一段汇编代码来实现返回操作系统,则printf向终端输出的字符流中,终端只显示字符流中最后一个\n符号前面的字符。 * 如果字符流没有\n,则所在字符都不能正常显示出来。 * 比如返回操作系统前,printf总共向终端输出如下字符流: * * XXXXXXXXXXX\n * Xxxxxxxxxxxxxxxx\n\xxxxxx * xxxxxxxxxxxxxx\n * YYYYYYYYYYYYYYYyyyyyy * * 这样最后一符的所有Y都不会显示出来,事实上是最后一个\n后面的所有字符都不会在终端前面显示出来。 * * 测试环境 * gcc版本: * gcc (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5 * ubuntu版本: * Linux abee-lisa-linux 2.6.35-32-generic #64-Ubuntu SMP Mon Jan 2 23:31:33 UTC 2012 i686 GNU/Linux * * 目前暂不知道到底这个软中断具体做了什么,so..留着有待研究咯. */ /* 哪个大哥大姐知道这是怎么回事的,望指点指点迷津呀。 ^_^ */ #include <stdio.h> int main() { printf("this is a string with \\n \n"); printf("this is a string with \\n \n"); printf("this is a string without \\n"); /* 直接内联汇编 */ __asm__("movl $1,%eax\n \ movl $0,%ebx\n \ int $0x80"); //是返回操作系统了,并以返回值0返回。但是却影响了终端的显示。 //exit(0); /* 真正的exit(0); */ return 0; } /* 正常的输出应该是: * this is a string with \n * this is a string with \n * this is a string without \n * 但是,如果采用不同的返回操作系统的方式,結果是不一样的。 */
原因解释(2014-11-01):
这里有个背景:针对终端设置,printf输出缓冲模式是行模式,即遇到\n就会真正flush到终端上,否则先缓存,直到缓冲区满了才flush到终端上。
这里内联汇编中的代码实现的是返回操作系统,注意这里是直接由汇编代码返回,因此隐藏了一个程序在正常返回操作系统之前所隐藏的逻辑,如关闭文件、清空缓存区等等。
这里最后一个\n后面的没有输出的原因就是少了正常退出所做的清空缓存逻辑,这段代码和_exit(0)功能一样(注意是_exit(),需包含unistd.h)。
对于exit(0)和return 0;这两个方式其实都含有清空缓存区的逻辑,因此在返回操作系统前会正常见到预期输出的数据。