_spawn、_wspawn 函数_spawn, _wspawn Functions

每个 _spawn 函数将创建并执行一个新进程:Each of the _spawn functions creates and executes a new process:

_spawnl、_wspawnl_spawnl, _wspawnl _spawnv、_wspawnv_spawnv, _wspawnv
_spawnle、_wspawnle_spawnle, _wspawnle _spawnve、_wspawnve_spawnve, _wspawnve
_spawnlp、_wspawnlp_spawnlp, _wspawnlp _spawnvp、_wspawnvp_spawnvp, _wspawnvp
_spawnlpe、_wspawnlpe_spawnlpe, _wspawnlpe _spawnvpe、_wspawnvpe_spawnvpe, _wspawnvpe

函数名称的结尾字母确定变体。The letters at the end of the function name determine the variation.

e
指向环境设置的指针的数组 envp 将传递给新进程。envp, array of pointers to environment settings, is passed to new process.

l
将命令行参数单独传递给 _spawn 函数。Command-line arguments are passed individually to _spawn function. 一般将在预先知道新进程的一些参数时使用此后缀。This suffix is typically used when a number of parameters to a new process is known in advance.

p
PATH 环境变量用于查找要执行的文件。PATH environment variable is used to find the file to execute.

v
指向命令行参数的指针的数组 argv 将传递给 _spawn 函数。argv, array of pointers to command-line arguments, is passed to _spawn function. 一般在新进程的一些参数可变时使用此后缀。This suffix is typically used when a number of parameters to a new process is variable.

备注Remarks

每个 _spawn 函数都将创建并执行一个新进程。The _spawn functions each create and execute a new process. 它们将根据情况自动处理多字节字符串参数,根据当前正在使用中的多字节代码页识别多字节字符序列。They automatically handle multibyte-character string arguments as appropriate, recognizing multibyte-character sequences according to the multibyte code page currently in use. _wspawn 函数是 _spawn 函数的宽字符版本;它们不处理多字节字符串。The _wspawn functions are wide-character versions of the _spawn functions; they do not handle multibyte-character strings. 否则,_wspawn 函数的行为将与其 _spawn 对等函数的一致。Otherwise, the _wspawn functions behave identically to their _spawn counterparts.

一般文本例程映射Generic-Text Routine Mappings

Tchar.h 例程Tchar.h routine 未定义 _UNICODE 和 _MBCS_UNICODE and _MBCS not defined 已定义 _MBCS_MBCS defined 已定义 _UNICODE_UNICODE defined
_tspawnl _spawnl _spawnl _wspawnl
_tspawnle _spawnle _spawnle _wspawnle
_tspawnlp _spawnlp _spawnlp _wspawnlp
_tspawnlpe _spawnlpe _spawnlpe _wspawnlpe
_tspawnv _spawnv _spawnv _wspawnv
_tspawnve _spawnve _spawnve _wspawnve
_tspawnvp _spawnvp _spawnvp _wspawnvp
_tspawnvpe _spawnvpe _spawnvpe _wspawnvpe

加载和执行新进程必须有足够的内存可用。Enough memory must be available for loading and executing the new process. mode 参数确定调用进程在 _spawn 之前以及期间将执行的操作。The mode argument determines the action taken by the calling process before and during _spawn. mode 的下列值是在 Process.h 中定义的:The following values for mode are defined in Process.h:

_P_OVERLAY
使用新进程覆盖调用进程,销毁调用进程(效果与 _exec 调用相同)。Overlays a calling process with a new process, destroying the calling process (same effect as _exec calls).

_P_WAIT
在新进程执行完成之前挂起调用线程(同步 _spawn)。Suspends a calling thread until execution of the new process is complete (synchronous _spawn).

_P_NOWAIT_P_NOWAITO_P_NOWAIT or _P_NOWAITO
继续与新进程一起并发执行调用进程(异步 _spawn)。Continues to execute a calling process concurrently with the new process (asynchronous _spawn).

_P_DETACH
继续执行调用进程;新进程将在后台运行,而且不会访问控制台或键盘。Continues to execute the calling process; the new process is run in the background with no access to the console or keyboard. 针对新进程调用 _cwait 将失败(异步 _spawn)。Calls to _cwait against the new process fail (asynchronous _spawn).

cmdname 参数指定将作为新进程执行的文件,并可以指定完整路径(从根)、部分路径(从当前工作目录)或仅指定文件名。The cmdname argument specifies the file that is executed as the new process and can specify a full path (from the root), a partial path (from the current working directory), or just a file name. 如果 cmdname 没有文件扩展名或不是以句点 (.) 结尾的,则 _spawn 函数将先依次尝试 .com 文件扩展名、.exe 文件扩展名、.bat 文件扩展名和 .cmd 文件扩展名。If cmdname does not have a file name extension or does not end with a period (.), the _spawn function first tries the .com file name extension and then the .exe file name extension, the .bat file name extension, and finally the .cmd file name extension.

如果 cmdname 具有文件扩展名,则仅使用该扩展名。If cmdname has a file name extension, only that extension is used. 如果 cmdname 以句点结尾,则 _spawn 调用将搜索不带文件扩展名的 cmdnameIf cmdname ends with a period, the _spawn call searches for cmdname with no file name extension. _spawnlp_spawnlpe_spawnvp_spawnvpe 函数将在 PATH 环境变量指定的目录中搜索 cmdname(使用相同过程)。The _spawnlp, _spawnlpe, _spawnvp, and _spawnvpe functions search for cmdname (using the same procedures) in the directories specified by the PATH environment variable.

如果 cmdname 包含驱动器名或任何斜线(即,如果它是相对路径),则 _spawn 调用将仅搜索指定文件;不会执行路径搜索。If cmdname contains a drive specifier or any slashes (that is, if it is a relative path), the _spawn call searches only for the specified file; no path searching is done.

以前,这些函数中部分函数在成功时将 errno 设置为零;当前行为是在成功时保持不改动 errno,如 C 标准所指定。In the past, some of these functions set errno to zero on success; the current behavior is to leave errno untouched on success, as specified by the C standard. 如果需要模拟这一旧行为,请在调用这些函数之前将 errno 设置为零。If you need to emulate the old behavior, set errno to zero just before calling these functions.

备注

若要确保正确覆盖初始化和终止,请勿使用 setjmplongjmp 函数进入或离开覆盖例程。To ensure proper overlay initialization and termination, do not use the setjmp or longjmp function to enter or leave an overlay routine.

生成进程的参数Arguments for the Spawned Process

若要将参数传递给新进程,请在 _spawn 调用中将一个或多个指向字符串的指针作为参数提供。To pass arguments to the new process, give one or more pointers to character strings as arguments in the _spawn call. 这些字符串构成了生成进程的参数列表。These character strings form the argument list for the spawned process. 构成新进程参数列表的字符串的组合长度不得超过 1024 个字节。The combined length of the strings forming the argument list for the new process must not exceed 1024 bytes. 每个字符串的终止 null 字符 (“\0”) 不包含在计数中,但是空格字符(自动插入以分隔参数)包括在内。The terminating null character ('\0') for each string is not included in the count, but space characters (automatically inserted to separate arguments) are included.

备注

嵌入字符串中的空格可能导致意外行为;例如,将字符串 _spawn 传递给 "hi there" 会导致新进程获得两个参数:"hi""there"Spaces embedded in strings may cause unexpected behavior; for example, passing _spawn the string "hi there" will result in the new process getting two arguments, "hi" and "there". 如果想要让新进程打开名为“hi there”的文件,则该进程将失败。If the intent was to have the new process open a file named "hi there", the process would fail. 你可以通过引用字符串 "\"hi there\"" 来避免此问题。You can avoid this by quoting the string: "\"hi there\"".

重要

如果没有显式地检查其内容,请不要将用户输入传递给 _spawnDo not pass user input to _spawn without explicitly checking its content. _spawn 将导致调用 CreateProcess,因此请牢记,未限定的路径名称可能会导致潜在的安全漏洞。_spawn will result in a call to CreateProcess so keep in mind that unqualified path names could lead to potential security vulnerabilities.

您可以将参数指针作为不同的参数传递(在 _spawnl_spawnle_spawnlp_spawnlpe 中)或作为指针数组传递(在 _spawnv_spawnve_spawnvp_spawnvpe 中)。You can pass argument pointers as separate arguments (in _spawnl, _spawnle, _spawnlp, and _spawnlpe) or as an array of pointers (in _spawnv, _spawnve, _spawnvp, and _spawnvpe). 您必须至少将一个参数 arg0argv[0] 传递到生成进程。You must pass at least one argument, arg0 or argv[0], to the spawned process. 按照约定,此参数是程序的名称,因为您将在命令行上键入该名称。By convention, this argument is the name of the program as you would type it on the command line. 不同的值不会生成错误。A different value does not produce an error.

一般将在提前知道参数数量的情况下使用 _spawnl_spawnle_spawnlp_spawnlpe 调用。The _spawnl, _spawnle, _spawnlp, and _spawnlpe calls are typically used in cases where the number of arguments is known in advance. arg0 参数通常是指向 cmdname的指针。The arg0 argument is usually a pointer to cmdname. 参数 arg1argn 是指向构成新参数列表的字符字符串的指针。The arguments arg1 through argn are pointers to the character strings forming the new argument list. argn之后,必须是一个 NULL 指针,用以标记参数列表的末尾。Following argn, there must be a NULL pointer to mark the end of the argument list.

_spawnv_spawnve_spawnvp_spawnvpe 调用在新进程具有数量可变的参数时很有用。The _spawnv, _spawnve, _spawnvp, and _spawnvpe calls are useful when there is a variable number of arguments to the new process. 指向参数的指针将作为数组 argv 传递。Pointers to the arguments are passed as an array, argv. 参数 argv[0] 通常是一个指向实际模式中的路径或保护模式中的程序的指针,从 argv[1] 到 argv[n] 都是指向构成新参数列表的字符串的指针。The argument argv[0] is usually a pointer to a path in real mode or to the program name in protected mode, and argv[1] through argv[n] are pointers to the character strings forming the new argument list. 参数 argv[n +1] 必须是一个 NULL 指针,用以标记参数列表的末尾。The argument argv[n +1] must be a NULL pointer to mark the end of the argument list.

生成进程的环境Environment of the Spawned Process

调用 _spawn 时打开的文件在新进程中仍处于打开状态。Files that are open when a _spawn call is made remain open in the new process. _spawnl_spawnlp_spawnv_spawnvp 调用中,新进程将继承调用进程的环境。In the _spawnl, _spawnlp, _spawnv, and _spawnvp calls, the new process inherits the environment of the calling process. 您可以使用 _spawnle_spawnlpe_spawnve_spawnvpe 调用更改新进程的环境,方式为通过 envp 参数传递环境设置的列表。You can use the _spawnle, _spawnlpe, _spawnve, and _spawnvpe calls to alter the environment for the new process by passing a list of environment settings through the envp argument. 参数 envp 是字符指针的数组,其中每个元素(除了最后一个元素)均指向一个定义环境变量的不以 null 结尾的字符串。The argument envp is an array of character pointers, each element (except the final element) of which points to a null-terminated string defining an environment variable. 此类字符串通常具有 NAME=value 格式,其中 NAME 是环境变量的名称,value 是为该变量设置的字符串值。Such a string usually has the form NAME=value where NAME is the name of an environment variable and value is the string value to which that variable is set. (请注意,value 并未括在双引号中。)envp 数组的最后一个元素应该是 NULL(Note that value is not enclosed in double quotation marks.) The final element of the envp array should be NULL. envp 本身为 NULL 时,生成进程将继承父进程的环境设置。When envp itself is NULL, the spawned process inherits the environment settings of the parent process.

_spawn 函数可将所有有关打开的文件(包括转换模式)的信息传递到新进程。The _spawn functions can pass all information about open files, including the translation mode, to the new process. 此信息将在实模式下通过环境中的 C_FILE_INFO 条目传递。This information is passed in real mode through the C_FILE_INFO entry in the environment. 启动代码通常会处理此条目,然后将其从环境中删除。The startup code normally processes this entry and then deletes it from the environment. 但是,如果 _spawn 函数生成一个非 C 进程,则此条目仍将保留在环境中。However, if a _spawn function spawns a non-C process, this entry remains in the environment. 打印环境将在此条目的定义字符串中显示图形字符,因为环境信息在实模式下是以二进制格式传递的。Printing the environment shows graphics characters in the definition string for this entry because the environment information is passed in binary form in real mode. 它不应对正常操作具有任何其他影响。It should not have any other effect on normal operations. 在保护模式下,环境信息是以文本形式传递的,因此不包含图形字符。In protected mode, the environment information is passed in text form and therefore contains no graphics characters.

在调用 fflush 函数之前,您必须显式刷新(使用 _flushall_spawn)或关闭任何流。You must explicitly flush (using fflush or _flushall) or close any stream before calling a _spawn function.

通过调用 _spawn 例程创建的新进程不会保留任何信号设置。New processes created by calls to _spawn routines do not preserve signal settings. 而生成进程会将信号设置重置为默认值。Instead, the spawned process resets signal settings to the default.

重定向输出Redirecting Output

如果从 DLL 或 GUI 应用程序调用 _spawn 并希望将输出重定向至管道,则您具有两个选择:If you are calling _spawn from a DLL or a GUI application and want to redirect the output to a pipe, you have two options:

  • 使用 Win32 API 创建管道,然后调用 AllocConsole,在启动结构中设置句柄值,然后调用 CreateProcessUse the Win32 API to create a pipe, then call AllocConsole, set the handle values in the startup structure, and call CreateProcess.

  • 调用 _popen、_wpopen 以创建管道,并使用 cmd.exe /c(或 command.exe /c)调用应用。Call _popen, _wpopen which will create a pipe and invoke the app using cmd.exe /c (or command.exe /c).

示例Example

// crt_spawn.c  
// This program accepts a number in the range  
// 1-8 from the command line. Based on the number it receives,  
// it executes one of the eight different procedures that  
// spawn the process named child. For some of these procedures,  
// the CHILD.EXE file must be in the same directory; for  
// others, it only has to be in the same path.  
//  

#include <stdio.h>  
#include <process.h>  

char *my_env[] =  
{  
   "THIS=environment will be",  
   "PASSED=to child.exe by the",  
   "_SPAWNLE=and",  
   "_SPAWNLPE=and",  
   "_SPAWNVE=and",  
   "_SPAWNVPE=functions",  
   NULL  
};  

int main( int argc, char *argv[] )  
{  
   char *args[4];  

   // Set up parameters to be sent:   
   args[0] = "child";  
   args[1] = "spawn??";  
   args[2] = "two";  
   args[3] = NULL;  

   if (argc <= 2)  
   {  
      printf( "SYNTAX: SPAWN <1-8> <childprogram>\n" );  
      exit( 1 );  
   }  

   switch (argv[1][0])   // Based on first letter of argument   
   {  
   case '1':  
      _spawnl( _P_WAIT, argv[2], argv[2], "_spawnl", "two", NULL );  
      break;  
   case '2':  
      _spawnle( _P_WAIT, argv[2], argv[2], "_spawnle", "two",   
               NULL, my_env );  
      break;  
   case '3':  
      _spawnlp( _P_WAIT, argv[2], argv[2], "_spawnlp", "two", NULL );  
      break;  
   case '4':  
      _spawnlpe( _P_WAIT, argv[2], argv[2], "_spawnlpe", "two",   
                NULL, my_env );  
      break;  
   case '5':  
      _spawnv( _P_OVERLAY, argv[2], args );  
      break;  
   case '6':  
      _spawnve( _P_OVERLAY, argv[2], args, my_env );  
      break;  
   case '7':  
      _spawnvp( _P_OVERLAY, argv[2], args );  
      break;  
   case '8':  
      _spawnvpe( _P_OVERLAY, argv[2], args, my_env );  
      break;  
   default:  
      printf( "SYNTAX: SPAWN <1-8> <childprogram>\n" );  
      exit( 1 );  
   }  
   printf( "from SPAWN!\n" );  
}  
child process output  
from SPAWN!  

请参阅See Also

进程和环境控制 Process and Environment Control
abort abort
atexit atexit
_exec、_wexec 函数 _exec, _wexec Functions
exit、_Exit、_exit exit, _Exit, _exit
_flushall _flushall
_getmbcp _getmbcp
_onexit、_onexit_m _onexit, _onexit_m
_setmbcp _setmbcp
system、_wsystemsystem, _wsystem