11.1.4 MSVC CRT的入口函数初始化(2)
在这里_ioinit初始化了的__pioinfo[0]里的每一个元素为无效值,其中 INVALID_ HANDLE_VALUE是Windows句柄的无效值,值为 1。接下来,_ioinit的工作是将一些预定义的打开文件给初始化,这包括两部分:
(1) 从父进程继承的打开文件句柄,当一个进程调用API创建新进程的时候,可以选择继承自己的打开文件句柄,如果继承,子进程可以直接使用父进程的打开文件句柄。
(2) 操作系统提供的标准输入输出。
应用程序可以使用API GetStartupInfo来获取继承的打开文件,GetStartupInfo的参数如下:
void GetStartupInfo(STARTUPINFO* lpStartupInfo); |
typedef struct _STARTUPINFO { |
这两个字段的用途没有正式的文档说明,但实际是用来传递继承的打开文件句柄。当这两个字段的值都不为0时,说明父进程遗传了一些打开文件句柄。操作系统是如何使用这两个字段传递句柄的呢?首先lpReserved2字段实际是一个指针,指向一块内存,这块内存的结构如下:
字节[0,3]:传递句柄的数量n。
字节[4, 3+n]:每一个句柄的属性(各1字节,表明句柄的属性,同ioinfo结构的_osfile字段)。
字节[4+n之后]:每一个句柄的值(n个intptr_t类型数据,同ioinfo结构的_osfhnd字段)。
_ioinit函数使用如下代码获取各个句柄的数据:
cfi_len = *(__unaligned int *)(StartupInfo.lpReserved2); |
|
| (点击查看大图)图11-6 句柄属性数组和句柄数组 |
cfi_len = __min( cfi_len, 32 * 64 ); |
然后要给打开文件表分配足够的空间以容纳所有的句柄:
for ( i = 1 ; _nhandle < cfi_len ; i++ ) { |
在这里,nhandle总是等于已经分配的元素数量,因此只需要每次分配一个第二维的数组,直到nhandle大于cfi_len即可。由于__pioinfo[0]已经预先分配了,因此直接从__pioinfo[1]开始分配即可。分配了空间之后,将数据填入就很容易了:
for ( fh = 0 ; fh < cfi_len ; fh++, posfile++, posfhnd++ ) |
【责任编辑:云霞 TEL:(010)68476606】
| 回书目 上一节 下一节 |
