设为首页 加入收藏

TOP

11.1.4 MSVC CRT的入口函数初始化(2)
2013-10-07 00:43:29 来源: 作者: 【 】 浏览:60
Tags:11.1.4 MSVC CRT 入口 函数 初始

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);
STARTUPINFO是一个结构,调用GetStartupInfo之后,该结构就会被写入各种进程启动相关的数据。在该结构中,有两个保留字段为:
typedef struct _STARTUPINFO {
……
WORD cbReserved2;
LPBYTE lpReserved2;
……
} 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);
posfile = (char *)(StartupInfo.lpReserved2) + sizeof( int );
posfhnd = (__unaligned intptr_t *)(posfile + cfi_len);
其中__unaligned关键字告诉编译器该指针可能指向一个没有进行数据对齐的地址,编译器会插入一些代码来避免发生数据未对齐而产生的错误。这段代码执行之后,lpReserved2指向的数据结构会被两个指针分别指向其中的两个数组,如图11-6所示。
 
(点击查看大图)图11-6  句柄属性数组和句柄数组
接下来_ioinit就要将这些数据填入自己的打开文件表中。当然,首先要判断直接的打开文件表是否足以容纳所有的句柄:
cfi_len = __min( cfi_len, 32 * 64 );

然后要给打开文件表分配足够的空间以容纳所有的句柄:

for ( i = 1 ; _nhandle < cfi_len ; i++ ) {
if ( (pio = _malloc_crt( 32 * sizeof(ioinfo) )) == NULL )
{
cfi_len = _nhandle;
break;
}
__pioinfo[i] = pio;
_nhandle += 32;
for ( ; pio < __pioinfo[i] + 32 ; pio++ ) {
pio->osfile = 0;
pio->osfhnd = (intptr_t)INVALID_HANDLE_VALUE;
pio->pipech = 10;
}
}

在这里,nhandle总是等于已经分配的元素数量,因此只需要每次分配一个第二维的数组,直到nhandle大于cfi_len即可。由于__pioinfo[0]已经预先分配了,因此直接从__pioinfo[1]开始分配即可。分配了空间之后,将数据填入就很容易了:

for ( fh = 0 ; fh < cfi_len ; fh++, posfile++, posfhnd++ ) 
{
if ( (*posfhnd != (intptr_t)INVALID_HANDLE_VALUE) &&
(*posfile & FOPEN) &&
((*posfile & FPIPE) ||
(GetFileType( (HANDLE)*posfhnd ) !=
FILE_TYPE_UNKNOWN)) )
{
pio = _pioinfo( fh );
pio->osfhnd = *posfhnd;
pio->osfile = *posfile;
}
}

【责任编辑:云霞 TEL:(010)68476606】

回书目   上一节   下一节

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇11.1.4 MSVC CRT的入口函数初始化.. 下一篇11.1.4 MSVC CRT的入口函数初始化..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: