进程的创建与使用(win32-API)

news2024/11/15 13:02:30

一、前言

进程可以被视作操作系统中运行程序的一个实例,是系统资源分配和调度的基本单位。每一个进程都拥有自己独立的地址空间、一组状态信息(如打开的文件、内存映射等),以及一个或多个线程来执行代码。进程之间的隔离性确保了它们不会相互干扰,而这种隔离性也是多任务操作系统能够同时运行多个应用程序而不发生冲突的关键。

在程序设计中,进程提供了并发执行的基础,允许多个程序或程序的不同部分同时运行,从而提高了系统的效率和响应速度。其次,进程之间的通信(IPC)机制,如管道、消息队列、共享内存等,使得不同进程间的数据交换成为可能,这对于构建复杂的应用系统至关重要。进程为错误处理和资源管理提供了边界,例如,一个进程崩溃通常不会影响到其他进程的正常运行。

在Windows环境下,C语言可以通过调用Win32 API来创建和管理进程。 CreateProcess函数是最常用的方法。这个函数允许启动一个新的进程,并且可以控制其继承属性、优先级、环境变量等参数。

image-20240715145317183

以下是一个简单的示例,展示如何使用CreateProcess函数来创建一个新进程:

#include <windows.h>
#include <stdio.h>

int main() {
    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));

    // 尝试创建一个新进程
    if (!CreateProcess(NULL,   // 没有启动应用程序的路径,使用命令行
                      "notepad.exe", // 要启动的应用程序名
                      NULL,           // 进程的安全属性
                      NULL,           // 线程的安全属性
                      FALSE,          // 不继承句柄
                      0,              // 创建标志
                      NULL,           // 使用父进程的环境块
                      NULL,           // 使用父进程的当前目录
                      &si,            // STARTUPINFO结构
                      &pi) )          // PROCESS_INFORMATION结构
    {
        printf( "CreateProcess failed (%d).\n", GetLastError() );
        return 0;
    }

    // 等待子进程退出
    WaitForSingleObject(pi.hProcess, INFINITE);

    // 关闭进程和主程序句柄
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

    return 0;
}

在这个示例中,CreateProcess函数接收多个参数来指定新进程的特性,包括要启动的可执行文件名、安全属性、环境变量等。成功创建后,PROCESS_INFORMATION结构体将包含新进程和主线程的句柄,这些句柄可以用于进一步的进程管理操作,如等待进程结束、读取进程输出或向进程发送信号等。通过这种方式,C语言程序员可以在Windows平台上灵活地控制和管理进程,以实现复杂的系统级功能。

二、实操案例

2.1 CreateProcess函数详解

CreateProcess函数是Windows API中的一个重要成员,用于创建新的进程。允许启动一个可执行程序,并且可以控制新进程的属性,如环境、优先级、继承的句柄等。

以下是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// 进程信息
);
  • lpApplicationName: LPCTSTR类型,指向一个包含可执行文件全路径名的字符串。如果此参数为NULL,则lpCommandLine必须包含完整的可执行文件名和路径。

  • lpCommandLine: LPTSTR类型,指向一个包含命令行字符串的缓冲区。该字符串包含可执行文件名和所有命令行参数。如果lpApplicationName不为NULL,则lpCommandLine应仅包含参数列表。

  • lpProcessAttributes: LPSECURITY_ATTRIBUTES类型,指向一个描述新进程安全属性的结构体。如果不需要特殊的安全属性,则可以传递NULL

  • lpThreadAttributes: LPSECURITY_ATTRIBUTES类型,类似于lpProcessAttributes,但针对的是新进程的第一个线程。通常情况下,你也可以传递NULL

  • bInheritHandles: BOOL类型,指示新进程是否继承父进程的句柄。如果设为TRUE,那么父进程中所有可继承的句柄都会被继承;否则,新进程将不继承任何句柄。

  • dwCreationFlags: DWORD类型,是一个位掩码,用于指定创建进程的选项。常见的标志包括:

    • CREATE_NEW_CONSOLE: 如果创建的进程是一个控制台应用程序,那么即使它的父进程不是控制台应用程序,也会给它分配一个新的控制台窗口。
    • CREATE_SUSPENDED: 创建进程但不立即开始执行。
    • CREATE_NO_WINDOW: 如果创建的是控制台应用程序,则不显示其窗口。
    • DETACHED_PROCESS: 创建一个与父进程完全分离的进程。
  • lpEnvironment: LPVOID类型,指向一个环境块。这是由CreateEnvironmentBlock函数创建的环境变量集合。如果不需要修改环境变量,则可以传递NULL

  • lpCurrentDirectory: LPCTSTR类型,指向一个包含初始工作目录的字符串。如果未指定,则使用父进程的当前目录。

  • lpStartupInfo: LPSTARTUPINFO类型,指向一个STARTUPINFO结构体,它包含了有关如何创建新进程的信息,如控制台窗口大小、位置、标题等。

  • lpProcessInformation: LPPROCESS_INFORMATION类型,指向一个PROCESS_INFORMATION结构体,此结构体将在成功创建进程后填充,包含新进程的句柄和其他信息。

CreateProcess函数返回TRUE表示成功,如果失败,则返回FALSE,可以通过调用GetLastError函数来获取具体的错误代码。

在使用CreateProcess时,通常需要初始化STARTUPINFOPROCESS_INFORMATION结构体,确保它们的cb成员被正确设置为结构体的大小,以便CreateProcess函数知道结构体的确切大小。

2.2 调用ffmpeg转换视频

开发环境:在Windows下安装一个VS即可。我当前采用的版本是VS2020。

下面是一个具体的示例代码,演示了如何使用CreateProcess函数来启动FFmpeg并进行视频转换。在这个例子中,把一个MP4格式的视频转换成AVI格式。

前提是,要确保你的系统中已经安装了FFmpeg,并且其可执行文件路径已经被添加到了系统PATH环境变量中。这样,在调用CreateProcess时,你可以直接使用ffmpeg作为可执行文件名,而无需提供完整路径。

下面是C语言的示例代码:

#include <windows.h>
#include <stdio.h>

int main() {
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    char commandLine[1024];

    // 设置命令行参数,这里我们假定源文件名为"input.mp4",目标文件名为"output.avi"
    sprintf(commandLine, "ffmpeg -i input.mp4 output.avi");

    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));

    // 创建一个新进程,注意这里的NULL代表使用默认的环境变量
    if (!CreateProcess(NULL,
                       commandLine,
                       NULL,
                       NULL,
                       FALSE,
                       0,
                       NULL,
                       NULL,
                       &si,
                       &pi))
    {
        printf("CreateProcess failed with error code: %d\n", GetLastError());
        return 1;
    }

    // 等待子进程结束
    WaitForSingleObject(pi.hProcess, INFINITE);

    // 关闭句柄
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

    return 0;
}

这段代码中,使用sprintf函数来构造FFmpeg的命令行参数。这里,假设输入文件名为input.mp4,输出文件名为output.aviCreateProcess函数被用来启动FFmpeg进程,并传入上述构造的命令行字符串。WaitForSingleObject函数则确保程序会等到FFmpeg完成视频转换后再继续执行。

2.3 同时启动多个进程

开发环境:在Windows下安装一个VS即可。我当前采用的版本是VS2020。

要在C语言中同时运行三个FFmpeg进程以转换三个不同的视频文件,可以创建三个进程并将它们分别放入一个数组中。 使用WaitForMultipleObjects函数来等待所有进程完成。

下面是一个示例代码,展示了如何实现这一功能:

#include <windows.h>
#include <stdio.h>

#define NUM_PROCESSES 3

void create_ffmpeg_process(const char *inputFile, const char *outputFile, PROCESS_INFORMATION *pi)
{
    STARTUPINFO si;
    char commandLine[1024];

    // 构造FFmpeg命令行
    sprintf(commandLine, "ffmpeg -i \"%s\" \"%s\"", inputFile, outputFile);

    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(pi, sizeof(*pi));

    // 创建进程
    if (!CreateProcess(NULL, 
                       commandLine,
                       NULL, 
                       NULL, 
                       FALSE, 
                       0, 
                       NULL, 
                       NULL, 
                       &si, 
                       pi))
    {
        printf("CreateProcess failed for %s -> %s with error code: %d\n", inputFile, outputFile, GetLastError());
    }
}

int main()
{
    PROCESS_INFORMATION pi[NUM_PROCESSES];
    HANDLE hEvents[NUM_PROCESSES];
    DWORD waitResult;

    // 创建三个FFmpeg进程
    create_ffmpeg_process("video1.mp4", "video1_converted.avi", &pi[0]);
    create_ffmpeg_process("video2.mp4", "video2_converted.avi", &pi[1]);
    create_ffmpeg_process("video3.mp4", "video3_converted.avi", &pi[2]);

    // 准备事件句柄数组
    for (int i = 0; i < NUM_PROCESSES; i++)
    {
        hEvents[i] = pi[i].hProcess;
    }

    // 等待所有进程完成
    waitResult = WaitForMultipleObjects(NUM_PROCESSES, hEvents, TRUE, INFINITE);
    if (waitResult == WAIT_FAILED)
    {
        printf("WaitForMultipleObjects failed with error code: %d\n", GetLastError());
        return 1;
    }

    // 关闭所有句柄
    for (int i = 0; i < NUM_PROCESSES; i++)
    {
        CloseHandle(pi[i].hProcess);
        CloseHandle(pi[i].hThread);
    }

    return 0;
}

在这段代码中,定义了一个create_ffmpeg_process函数,接受输入文件名、输出文件名和一个PROCESS_INFORMATION结构体作为参数,用于创建单个FFmpeg进程。在main函数中,为每个视频文件调用这个函数,创建三个进程,并将每个进程的句柄存放在一个数组中。

使用WaitForMultipleObjects函数来等待所有三个进程完成。这个函数会阻塞,直到所有指定的事件(在这里是进程句柄)都被满足,即所有进程都已退出。最后,遍历进程信息数组,关闭所有的进程和线程句柄。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2081650.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

飞睿智能家居人体微动感知雷达模组,宠物喂食器、LED灯控连续波雷达感应开关原理

在智能家居的浪潮中&#xff0c;飞睿智能人体微动感知雷达模组犹如一位“隐形守护者”&#xff0c;以其独特的连续波雷达感应开关原理&#xff0c;为我们带来更为智能、便捷的生活体验。今天&#xff0c;就让我们一起走进这一前沿科技&#xff0c;探索它是如何改变我们的生活。…

IOS 13 网络请求和Moya框架

允许HTTP请求 从iOS9开始&#xff0c;推荐使用HTTPS&#xff0c;如果使用的HTTP&#xff0c;默认情况下会出现如下错误&#xff1a; The resource could not be loaded because the App Transport Security policy requires the use of a secure connection. 这是因为iOS9引…

中俄联袂 助力前行 点燃希望——助残义诊在杭州邦尔骨科医院顺利举行

8月26日&#xff0c;由杭州市残疾人联合会主办、临平区残疾人联合会承办&#xff0c;杭州市邦尔骨科医院协办的“中俄联袂 助力前行 点燃希望”助残义诊活动在该院1号楼门诊大厅顺利进行。此次活动得到了俄罗斯伊里扎洛夫中心医院和杭州市邦尔骨科医院专家的大力支持。 本次义诊…

珈创生物业绩下滑:毛利率连年大降,产能利用率滑坡仍募资扩产

《港湾商业观察》廖紫雯 日前&#xff0c;武汉珈创生物技术股份有限公司&#xff08;以下简称&#xff1a;珈创生物&#xff09;于北交所证券交易中心披露招股书&#xff0c;保荐机构为国投证券。 珈创生物往年IPO进程可谓一波三折。2020年12月&#xff0c;公司曾申报沪交所科…

双向NAT应用场景和配置

域内双向NAT&#xff08;端口回流&#xff09; 局域网内有一台或多台服务器可能需要对外映射提供服务&#xff0c;如内网终端也需要访问&#xff0c;这时如终端通过映射后的公网地址访问会出现无法访问的情况&#xff0c;这时就需要域内双向NAT&#xff08;华三很多路由器会有…

window下kafka3启动多个

准备工作 我们先安装好kafka&#xff0c;并保证启动成功&#xff0c;可参考文章Windows下安装Kafka3-CSDN博客 复制kafka安装文件 kafka3已经内置了zookeeper&#xff0c;所以直接复制就行了 修改zookeeper配置文件 这里我们修改zookeeper配置文件&#xff0c;主要是快照地址…

学习分享:手把手教你使用Python开发一个api数据接口

今天想和大家分享一下Python开发语言&#xff0c;为什么选择Python&#xff0c;因为当今生活中人工智能无处不在&#xff0c;而开发人工智能的首选语言必是Python。今天教大家使用Python开发一个api接口。 Python的开发环境我使用的是PyCharm&#xff0c;安装完成之后创建项目…

单域名SSL证书快速获取指南

在当今互联网的社会&#xff0c;网站安全变得非常重要。SSL证书&#xff0c;作为实现网站HTTPS加密通信的重要手段&#xff0c;不仅能够保护用户数据传输的安全&#xff0c;还能提升网站的信任度和搜索引擎排名等。其中单域名SSL证书是可以保护单个域名的网站&#xff0c;这对于…

TensorBoard快速入门

一、简介 TensorBoard是一套 Web 应用程序&#xff0c;用于检查和了解 TensorFlow 运行和图形。简而言之&#xff0c;就是用于机器学习可视化的工具 TensorBoard 设计为完全离线运行&#xff0c;无需任何 Internet 访问权限。例如&#xff0c;这可能位于本地计算机上、公司防…

团队合作新风向:2024年8款协作工具榜单

文章介绍了以下几个团队协作工具&#xff1a;1. Worktile&#xff1b;2. PingCode&#xff1b;3. 飞书&#xff1b;4. 钉钉&#xff1b;5. Wrike&#xff1b;6. 云之家&#xff1b;7. Tapd&#xff1b;8. Slack。 在2024年&#xff0c;随着远程工作和分布式团队的普及&#xff…

从消费市场看电动汽车和充电桩互动关系

中国电动汽车充电基础设施促进联盟&#xff08;以下简称促进联盟&#xff09;日前发布的最新统计数据显示&#xff0c;7月全国新增公共充电桩8.8万台&#xff0c;同比增长45.2%&#xff0c;连续多月保持同比四成以上增长&#xff1b;今年前7个月全国充电基础设施增量为200.8万台…

MATLAB绘图基础1:MATLAB基础回顾

参考书&#xff1a;《 M A T L A B {\rm MATLAB} MATLAB与学术图表绘制》(关东升)。 1.MATLAB基础回顾 1.1 MATLAB语言特点 M A T L A B {\rm MATLAB} MATLAB是一种解释型语言&#xff0c;允许用户逐步执行命令并立即查看结果&#xff1b; M A T L A B {\rm MATLAB} MATLAB拥有…

1996-2022年各省农村用电量数据(无缺失)

1996-2022年各省农村用电量数据&#xff08;无缺失&#xff09; 1、时间&#xff1a;1996-2022年 2、来源&#xff1a;国家统计局、农村统计年鉴、电力企业联合会 3、指标&#xff1a;农村用电量 4、范围&#xff1a;31省 5、缺失情况&#xff1a;无缺失 6、指标说明&…

SAP与生产制造MPM系统集成案例

一、需求介绍 某公司为保证企业内部生产管理系统的多项基础数据的同步更新&#xff0c;确保各模块间信息的一致性和准确性&#xff0c;对后续的生产计划和物料管理打下基础&#xff0c;该公司将MPM系统和SAP系统经过SAP PO中间件集成平台进行了集成。MPM全称为Manufacturing…

面临快开学的孩子们,快看看莱莉是怎么利用数字时钟调整作息时间的吧!

网管小贾 / sysadm.cc “是谁订的西兰花匹萨&#xff1f;” “快吃我吧&#xff0c;我是有机的&#xff01;” 哦&#xff0c;糟糕&#xff01;莱莉昨晚又做恶梦了…… “不知道为什么&#xff0c;这几天总是翻来覆去的&#xff0c;莱莉看样子似乎不太走运&#xff01;” 厌…

Spark自定义函数例子

spark自定义函数&#xff0c;Spark sql 使用和dataFrame方式使用 #自定义函数名字 def convert_zdy(sex):return "男" if sex 1 else "女"if __name__ __main__:spark SparkSession.builder.master("local[*]").appName("自定义函数&qu…

PHP Vue学生档案管理系统:如何实现快速信息检索与数据安全?

&#x1f34a;作者&#xff1a;计算机毕设匠心工作室 &#x1f34a;简介&#xff1a;毕业后就一直专业从事计算机软件程序开发&#xff0c;至今也有8年工作经验。擅长Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等。 擅长&#xff1a;按照需求定制化开发项目…

echarts最新封装柱状图

父元素传入一次最多显示几个以及每次切换几个超出没两秒向右切换一个图表加载有动画效果动态更新数据实时显示屏幕尺寸改变自动适应字体大小自适应数值为0时&#xff0c;柱设置最小高度 组件 BarChart.vue <template><div class"w100 h100"><divref…

本专业不好找工作,也许可以试试嵌入式 嵌入式学习路线 从C语言到MCU开发

引言 到了毕业季&#xff0c;很多朋友仔细如何学习嵌入式&#xff0c;这个问题其实很难以回答&#xff0c;每个人的具体情况都不一样&#xff0c;也没有什么万能的方法&#xff0c;保证大家都能学好嵌入式。本篇文章&#xff0c;博主将结合我自己的经历和理解&#xff0c;谈论下…

案例研究:如何在复杂环境中增强自组织

现有价值流的重组代表了管理者在敏捷转型的背景下所面对的最大可能的战术挑战。它直接影响到组织交付和影响既定社会结构的能力。它也在两个域之间的边界上&#xff1a;繁杂且复杂&#xff1b;目标结构的某些方面以经验为基础&#xff0c;具有一定的确定性&#xff0c;但我们无…