11.1.4 MSVC CRT的入口函数初始化(3)
在这个循环中,fh从0开始递增,每次通过_pioinfo宏来转换为打开文件表中连续的对应元素,而posfile和posfhnd则依次递增以遍历每一个句柄的数据。在复制的过程中,一些不符合条件的句柄会被过滤掉,例如无效的句柄,或者不属于打开文件及管道的句柄,或者未知类型的句柄。
这段代码执行完成之后,继承来的句柄就全部复制完毕。接下来还须要初始化标准输入输出。当继承句柄的时候,有可能标准输入输出(fh=0,1,2)已经被继承了,因此在初始化前首先要先检验这一点,代码如下:
for ( fh = 0 ; fh < 3 ; fh++ ) { pio = __pioinfo[0] + fh; if ( pio->osfhnd == (intptr_t)INVALID_HANDLE_VALUE ) { pio->osfile = (char)(FOPEN | FTEXT); if ( ((stdfh = (intptr_t)GetStdHandle( stdhndl(fh) )) != (intptr_t)INVALID_HANDLE_VALUE) && ((htype =GetFileType( (HANDLE)stdfh )) != FILE_TYPE_UNKNOWN) ) { pio->osfhnd = stdfh; if ( (htype & 0xFF) == FILE_TYPE_CHAR ) pio->osfile |= FDEV; else if ( (htype & 0xFF) == FILE_TYPE_PIPE ) pio->osfile |= FPIPE; } else { pio->osfile |= FDEV; } } else { pio->osfile |= FTEXT; } } |
如果序号为0、1、2的句柄是无效的(没有继承自父进程),那么_ioinit会使用GetStdHandle函数获取默认的标准输入输出句柄。此外,_ioinit还会使用GetFileType来获取该默认句柄的类型,给_osfile设置对应的值。
在处理完标准数据输出的句柄之后,I/O初始化工作就完成了。我们可以看到,MSVC的I/O初始化主要进行了如下几个工作:
建立打开文件表。
如果能够继承自父进程,那么从父进程获取继承的句柄。
初始化标准输入输出。
在I/O初始化完成之后,所有的I/O函数就都可以自由使用了。在本节中,我们介绍了入口函数最重要的两个部分,堆初始化和I/O初始化,相信读者对程序的启动部分已经有了较深的理解。不过,入口函数只是冰山一角,它隶属的是一个庞大的代码集合。这个代码集合叫做运行库。
【责任编辑:
云霞 TEL:(010)68476606】