WinAPI执行外部程序和创建新进程:CreateProcess()的使用

WinAPI执行外部程序和创建新进程:CreateProcess()的使用

一、基本原理和流程

执行一个外部程序实质上可以认为就是创建一个进程

windows系统下创建一个进程意味着:

1、创建一个内核对象:内核对象是windows系统用于管理进程的一个工具,可以认为是一个数据结构。  

2、创建一个地址空间:用于存放可执行文件的代码和数据  

当调用CreateProcess()时,windows会自动创建一个进程内核对象,将进程内核对象引用计数设置为1,并将可执行文件的代码和数据加载到地址空间,然后再创建相应的主线程的内核对象,最终执行入口函数

二、CreateProcess的定义

BOOL CreateProcess 
( 
LPCTSTR lpApplicationName, 
LPTSTR lpCommandLine, 
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes, 
BOOL bInheritHandles, 
DWORD dwCreationFlags, 
LPVOID lpEnvironment, 
LPCTSTR lpCurrentDirectory, 
LPSTARTUPINFO lpStartupInfo, 
LPPROCESS_INFORMATION lpProcessInformation 
); 

三、参数详解

CreatProcess()需要若干参数来指定新进程的运行方式,但实际使用中多半参数都是用不到的,可以设置为NULL

1、lpApplicationName

这个参数用于指定可执行文件的名称也可以是可执行文件的路径

该参数的类型是LPCTSTR,其实就是一个const char*的传统C字符串,要求以’0’结尾,需要注意的是这必须是个常量字符串

需要注意的是在lpApplicationName中必须指定扩展名(.exe)并且如果没有指定路径,windows将只在当前目录中寻找,没有找到就会出错返回False。另一方面,即使指定了lpApplicationName也会把lpCommmandLine(命令行参数)原封不动的作为命

<think>好的,我现在需要帮助用户解决如何在C语言中创建进程的问题。用户已经提供了几个站内引用,我需要仔细查看这些引用,并结合用户之前的问题来给出合适的回答。 首先,用户之前的问题是关于`wait`函数的头文件,我回答了需要包含`sys/types.h``sys/wait.h`,并提到了与`fork()`一起使用。现在用户的新问题是关于创建进程的示例代码,所以需要重点讲解`fork()`的使用,可能还有Windows下的方法。 查看用户提供的引用,引用[3][4]提到`fork()`函数会创建进程,父进程进程的区别在于返回值。引用[2]是关于Windows使用`CreateProcess`的示例。引用[1]中的代码虽然是一个无限循环,但包含了`unistd.h`头文件,这可能进程相关,但例子本身没有创建进程。引用[5]是关于进程通信的共享内存,可能暂时用不上。 用户的需求是创建进程的示例代码,所以我需要分别给出Unix/LinuxWindows下的不同方法。在之前的回答中,用户提到`fork()`属于`unistd.h`,所以需要确保在Unix示例中包含这个头文件。同时,引用[2]中的`CreateProcess`示例需要详细说明,因为这是Windows特有的方法。 需要注意的是,用户可能是在不同的操作系统环境下工作,所以分开说明两种平台的实现方式是必要的。同时,要指出两种方法的区别,比如`fork()`是复制当前进程,而`CreateProcess`是创建新的进程执行指定程序。 另外,用户可能对进程创建的基本概念不太清楚,需要简要解释父进程进程的概念,以及`fork()`的返回值如何区分两者。引用[3][4]中提到的内容可以用来支持这些解释。 还要检查示例代码的正确性,比如在Unix示例中,`fork()`的返回值处理是否正确,父进程进程执行流程是否明确。在Windows示例中,`STARTUPINFO``PROCESS_INFORMATION`结构体的初始化是否正确,`CreateProcess`的参数是否合理。 最后,生成相关问题时要考虑用户可能接下来会问的内容,比如进程间通信、如何等待子进程、不同创建方式的区别等,这有助于用户进一步学习。</think>在C语言中创建进程主要有两种方式,我们通过不同系统平台的实现进行说明: ### 一、Unix/Linux系统(POSIX标准) ```c #include <stdio.h> #include <unistd.h> int main() { pid_t pid = fork(); // 创建进程的关键系统调用[^3][^4] if (pid == 0) { // 子进程执行分支 printf("子进程PID: %d\n", getpid()); execlp("/bin/ls", "ls", NULL); // 执行新程序 } else if (pid > 0) { // 父进程执行分支 printf("父进程PID: %d\n", getpid()); wait(NULL); // 等待子进程结束[^1] } else { perror("fork失败"); } return 0; } ``` **核心机制**: 1. `fork()`通过复制当前进程创建进程,形成并行执行的父子进程[^4] 2. 通过返回值区分父子进程: - 父进程获得子进程PID(正数) - 子进程获得0返回值 - 负数表示创建失败[^3] ### 二、Windows系统(WINAPI) ```c #include <windows.h> #include <stdio.h> int main() { STARTUPINFO si = { sizeof(si) }; // 必须初始化结构体大小[^2] PROCESS_INFORMATION pi; if(CreateProcess( NULL, // 不指定可执行文件路径 "notepad.exe", // 要启动的应用程序 NULL, NULL, FALSE, // 默认安全属性/不继承句柄 0, NULL, NULL, // 无特殊标志/使用进程环境 &si, &pi)) // 接收进程信息[^2] { printf("子进程PID: %d\n", pi.dwProcessId); CloseHandle(pi.hProcess); // 必须关闭句柄 } return 0; } ``` **关键差异**: - 直接创建新进程而非复制当前进程 - 需要显式指定要执行的程序路径[^2] ### 对比分析表 | 特性 | fork() | CreateProcess | |-------------------|----------------------|---------------------| | 进程创建方式 | 复制当前进程 | 创建新进程 | | 执行内容 | 继承父进程代码 | 指定外部可执行文件 | | 系统资源继承 | 文件描述符/环境变量 | 可选部分继承 | | 跨平台支持 | POSIX系统通用 | Windows专用 | --相关问题-- 1. 如何实现父子进程间的数据通信? 2. `fork()`与`vfork()`有什么区别? 3. Windows进程创建时如何设置环境变量? 4. 为什么Linux子进程需要调用`exec`系列函数? 5. 如何检测子进程的非正常终止?
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值