Windows系统编程(二)进程与线程一

进程与线程

进程:直观的讲就是任务管理器中我们看到的东西。

与内核对象句柄相似的,进程也有进程对象句柄,可以进行进程的各种操作如打开关闭。

每个进程都是独立的,在进程启动以后系统分配彼此独立的虚拟内存,此时进程会将其所有的代码等数据在虚拟内存中进行展开

进程本身不能执行代码,它是一种严谨的数据结构,用于进行管理相关工作。其在三环有一个结构叫做PEB,在0环有一个结构叫EPROCESS,这两个结构用于对进程进行管理工作。

一个进程可以有多个线程,它们存储在线程列表中。在如上的两个结构中都有一个项用于指向线程列表,而线程才是真正执行代码的东西

当进程启动时,主线程被启动,用于执行main函数

在单核处理器下,我们看到的多线程同时进行只是多线程在极短的时间内进行快速切换执行的假象,而在多核处理器下,每个核心都可以独立去执行单个线程,是真正意义上的多线程同时执行。

当主线程消失的时候,进程也随之销毁

在Windows下创建进程有多种形式,如WinExec(),system()等等,其本质是对CreateProcess()的封装

现我们通过一个完整的程序了解进程与线程

#include<Windows.h>
#include<iostream>
int main()
{//该结构体指定创建进程时的主窗口的窗口工作站,桌面,标准句柄和外观STARTUPINFO StartupInfo = { sizeof(STARTUPINFO) };//必须初始化该结构第一个成员cb,即该结构大小。利用sizeof是因为防止因Windows的更新迭代导致该结构发生变化导致结构大小错误//该结构体包含有关新创建的进程及其主线程的信息PROCESS_INFORMATION ProcessInformation;//创建进程BOOL bRet = CreateProcess(L"F:\\ChinaNet-EDU.exe",     //文件路径NULL,                                 //命令行参数NULL,                                 //进程安全属性NULL,                                 //主线程安全属性FALSE,                                //进程句柄是否可继承NULL,                                 //控制优先级类和进程的创建标志NULL,                                 //指向新进程的环境块的指针NULL,                                 //进程当前目录的完整路径&StartupInfo,                         //指向STARTUPINFO或STARTUPINFOA的指针&ProcessInformation                   //指向PROCESS_INFORMATION结构的指针);if (!bRet) {std::cout << "CreateProcess Failed!" << std::endl;}else {std::cout << "进程句柄:" << ProcessInformation.hProcess << std::endl;std::cout << "线程句柄:" << ProcessInformation.hThread << std::endl;std::cout << "进程ID:" << ProcessInformation.dwProcessId << std::endl;std::cout << "主线程ID:" << ProcessInformation.dwThreadId << std::endl;//CloseHandele(ProcessInformation.hThread);//CloseHandele(ProcessInformation.dwThreadId);//不使用句柄时,关闭}//关闭进程(只能关闭没有保护,即权限较低的进程)//TerminateProcess(ProcessInformation.hProcess, 0);//通过关闭主线程关闭进程TerminateThread(ProcessInformation.hThread, 0);//结束当前进程:ExitProcess(0);system("pause");return 0;
}

在上述程序中我们通过了进程句柄去结束我们自己的进程。但当我们想要结束不是我们自己创建的进程/线程时,我们可以通过任务管理器查找进程ID去获取进程句柄

#include<Windows.h>
#include<iostream>
int main()
{//如现在我们通过任务管理器得知一个进程ID:5340HANDLE hProcesss = OpenProcess(PROCESS_ALL_ACCESS,   //权限FALSE,                //可否继承5430                 //进程ID)//获取进程句柄if(hProcess==NULL)//当无法打开该进程,即打开不了权限较高的进程时{std::cout<<"OpenProcess Error Code:"<<GetLastError<<std::endl;}TerminateProcess(hProcess,0);return 0;
}

进程快照

在实际的应用中,我们不可能去通过任务管理器去查找进程ID,因为太耗费时间。因此我们可以通过进程快照来获取我们需要的进程ID并进行接下来的操作

#include<Windows.h>
#include<iostream>
#include <TlHelp32.h> //需要包含的头文件
int main()
{  //创建进程快照HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);//拿到第一个进程信息PROCESSENTRY32 pe32 = { sizeof(PROCESSENTRY32) };BOOL bRet = Process32First(hSnap, &pe32);//遍历进程快照while(bRet) {std::cout << pe32.szExeFile << ":" << lppe.th32ProcessID << std::endl;//打印进程名及ID//字符串比较if (strcmp(pe32.szExeFile, "ChinaNet-EDU.exe") == 0) //当遍历到我们想要打开的进程时{ //打开进程HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID);//关闭进程BOOL Ret = TerminateProcess(hProcess, 0);if (!Ret) {std::cout<<"TerminateProcess:"<<pe32.szExeFile<<"Failed Code :"<<std::endl;}}//继续找下一个进程bRet = Process32Next(hSnap, &lppe);}return 0;
}

线程的开关

//该程序有两个线程,一个主线程一个子线程
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>
DWORD ThreadCallBack(LPVOID lpThreadParameter) //此处是我们创建个一个子线程
{int i = 0;while (true){std::cout << "Thread:" << i++ << std::endl;Sleep(1000);}
}
int main()
{//用于接收线程IDDWORD dwThreadID;//创建线程HANDLE hThread = CreateThread(NULL,           //安全属性,结构体里面有一个成员,决定线程句柄是否可以继承NULL,           //堆栈大小,如果为NULL,则分配默认大小ThreadCallBack, //指向有线程执行的应用程序定义函数的指针NULL,           //指向由线程执行的应用程序传给线程的变量指针NULL,           //控制线程创建的标志:立即执行或挂起等状态&dwThreadID     //指向接收线程表示符的变量指针);int i = 0;while (true){std::cout << "Main:" << i++ << std::endl;Sleep(1000);} system("pause");return 0;
}

注意:当主线程关闭时,子线程也随之关闭

作业

1.实现线程快照功能


#include<Windows.h>
#include <iostream>
#include<TlHelp32.h>
int main()
{HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, NULL);if (hSnap == INVALID_HANDLE_VALUE){std::cout << "CreateToolhelp32Snapshot failed" << std::endl;return FALSE;}THREADENTRY32 hThread = { sizeof(THREADENTRY32) };BOOL bRet = Thread32First(hSnap, &hThread);while (bRet){std::cout << "ThreadID:" << hThread.th32ThreadID << std::endl;bRet = Thread32Next(hSnap, &hThread);if (bRet == FALSE){std::cout << "线程快照打印完毕" << std::endl;CloseHandle(hSnap);return FALSE;}}return 0;
}

2.尝试线程的挂起与恢复

#include<Windows.h>
#include<iostream>
#include<thread>
void FirstThread()
{std::cout << "FirstThread线程开始" << std::endl;int i = 0;for (int i = 0; i < 10000; i++){std::cout << "i = " << i << std::endl;}
}
int main()
{std::thread ThreadOne(FirstThread);SuspendThread(ThreadOne.native_handle());std::cout << "FirstThread被挂起" << std::endl;Sleep(3000);ResumeThread(ThreadOne.native_handle());std::cout << "FirstThread被唤起" << std::endl;ThreadOne.join();return 0;
}

3.使用MFC制作一个进程管理器(进程LIst)右键可以结束进程,可以打开线程列表(右键结束线程,挂起恢复线程)

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

web前端面试中拍摄的真实js面试题(真图)

web前端面试中拍摄的真实js面试题&#xff08;真图&#xff09; WechatIMG258.jpeg WechatIMG406.jpeg WechatIMG407.jpeg WechatIMG922.jpeg WechatIMG1063.jpeg © 著作权归作者所有,转载或内容合作请联系作者 喜欢的朋友记得点赞、收藏、关注哦&#xff01;&#xff01;…

TypeScript 算法手册 - 【冒泡排序】

文章目录 TypeScript 算法手册 - 冒泡排序1. 冒泡排序简介1.1 冒泡排序定义1.2 冒泡排序特点 2. 冒泡排序步骤过程拆解2.1 比较相邻元素2.2 交换元素2.3 重复过程 3. 冒泡排序的优化3.1 提前退出3.2 记录最后交换位置案例代码和动态图 4. 冒泡排序的优点5. 冒泡排序的缺点总结 …

【SpringBoot详细教程】-09-Redis详细教程以及SpringBoot整合Redis【持续更新】

🌲 Redis 简介 🌾 什么是Redis Redis 是C语言开发的一个开源高性能键值对的内存数据库,可以用来做数据库、缓存、消息中间件等场景,是一种NoSQL(not-only sql,非关系型数据库)的数据库 Redis是互联网技术领域使用最为广泛的存储中间件,它是「Remote DictionaryServic…

TARA分析方法论——威胁分析和风险评估方法

一、什么是TARA分析方法论 威胁分析和风险评估&#xff08;Threat Analysis and Risk Assessment&#xff09; 通过识别整车/项目的网络安全资产&#xff0c;分析其中的潜在的安全威胁&#xff0c;综合考虑威胁攻击可行性、危害影响等因素&#xff0c;识别出整车/项目可能存在…

Python并发编程(2)——初始Python多线程

左手编程&#xff0c;右手年华。大家好&#xff0c;我是一点&#xff0c;关注我&#xff0c;带你走入编程的世界。 公众号&#xff1a;一点sir&#xff0c;关注领取python编程资料 前言 什么是多线程&#xff1f; 为什么需要多线程&#xff1f; 多线程的优点和缺点&#xff1f…

前端规范工程-5:Git提交信息规范(commitlint + czg)

前面讲的都是在git提交之前的一些检查流程&#xff0c;然而我们git提交信息的时候&#xff0c;也应该是需要规范的。直接进入主题&#xff1a; 目录 需安装插件清单commitlint 介绍安装配置配置commit-msg钩子提交填写commit信息czg后续方式一&#xff1a;push触动build并上传…

Windows UAC权限详解以及因为权限不对等引发软件工具无法正常使用的实例分析

目录 ​1、什么是UAC&#xff1f; 2、微软为什么要设计UAC&#xff1f; 3、标准用户权限与管理员权限 4、程序到底以哪种权限运行&#xff1f;与哪些因素有关&#xff1f; 4.1、给程序设置以管理员权限运行的属性 4.2、当前登录用户的类型 4.3、如何通过代码判断某个进程…

2.1MyBatis——ORM对象关系映射

2.1MyBatis——ORM对象关系映射 1. 验证映射配置2.ResultType和ResultMap2.1ResultMap是最终的ORM依据2.2ResultType和ResultMap的使用区别 3.具体的转换逻辑3.1 TypeHandle类型转换 5.总结 概括的说&#xff0c;MyBatis中&#xff0c;对于映射关系的声明是由开发者在xml文件手…

手机USB连接不显示内部设备,设备管理器显示“MTP”感叹号,解决方案

进入小米驱动下载界面&#xff0c;等小米驱动下载完成后&#xff0c;解压此驱动文件压缩包。 5、小米USB驱动安装方法&#xff1a;右击“计算机”&#xff0c;从弹出的右键菜单中选择“管理”项进入。 6、在打开的“计算机管理”界面中&#xff0c;展开“设备管理器”项&…

【数据分享】2000—2023年我国省市县三级逐年植被覆盖度(FVC)数据(Shp/Excel格式)

之前我们分享过2000—2023年逐月植被覆盖度&#xff08;FVC&#xff09;栅格数据&#xff08;可查看之前的文章获悉详情&#xff09;和Excel和Shp格式的省市县三级逐月FVC数据&#xff08;可查看之前的文章获悉详情&#xff09;&#xff0c;原始的逐月栅格数据来源于高吉喜学者…

深度学习:迁移学习

目录 一、迁移学习 1.什么是迁移学习 2.迁移学习的步骤 1、选择预训练的模型和适当的层 2、冻结预训练模型的参数 3、在新数据集上训练新增加的层 4、微调预训练模型的层 5、评估和测试 二、迁移学习实例 1.导入模型 2.冻结模型参数 3.修改参数 4.创建类&#xff…

GAN|对抗| 生成器更新|判别器更新过程

如上图所示&#xff0c;生成对抗网络存在上述内容&#xff1a; 真实数据集&#xff1b;生成器&#xff1b;生成器损失函数&#xff1b;判别器&#xff1b;判别器损失函数&#xff1b;生成器、判别器更新&#xff08;生成器和判别器就是小偷和警察的关系&#xff0c;他们共用的…

kubernetes基础操作(pod生命周期)

pod生命周期 一、Pod生命周期 我们一般将pod对象从创建至终的这段时间范围称为pod的生命周期&#xff0c;它主要包含下面的过程&#xff1a; ◎pod创建过程 ◎运行初始化容器&#xff08;init container&#xff09;过程 ◎运行主容器&#xff08;main container&#xff…

记录一次病毒启动脚本

在第一次下载软件时&#xff0c;目录中配了一个使用说明&#xff0c;说是需要通过start.bat 这个文件来启动程序&#xff0c;而这个 start.bat 就是始作俑者&#xff1a; 病毒作者比较狡猾&#xff0c;其中start.bat 用记事本打开是乱码&#xff0c;但是可以通过将这个批处理…

spring揭秘24-springmvc02-5个重要组件

文章目录 【README】【1】HanderMapping-处理器映射容器【1.1】HanderMapping实现类【1.1.1】SimpleUrlHandlerMapping 【2】Controller&#xff08;二级控制器&#xff09;【2.1】AbstractController抽象控制器&#xff08;控制器基类&#xff09; 【3】ModelAndView(模型与视…

java入门基础(一篇搞懂)

​ 如果您觉得这篇文章对您有帮助的话 欢迎您分享给更多人哦 感谢大家的点赞收藏评论&#xff0c;感谢您的支持&#xff01;&#xff01;&#xff01; 首先给大家推荐比特博哥&#xff0c;java入门安装的JDk和IDEA社区版的安装视频 JDK安装与环境变量的配置 IDEA社区的安装与使…

帝国CMS系统开启https后,无法登陆后台的原因和解决方法

今天本地配置好了帝国CMS7.5&#xff0c;传去服务器后&#xff0c;使用http访问一切正常。但是当开启了https&#xff08;SSL&#xff09;后&#xff0c;后台竟然无法登陆进去了。 输入账号密码后&#xff0c;点击登陆&#xff0c;跳转到/e/admin/ecmsadmin.php就变成页面一片…

SpringBoot基础(三):Logback日志

SpringBoot基础系列文章 SpringBoot基础(一)&#xff1a;快速入门 SpringBoot基础(二)&#xff1a;配置文件详解 SpringBoot基础(三)&#xff1a;Logback日志 目录 一、日志依赖二、日志格式1、记录日志2、默认输出格式3、springboot默认日志配置 三、日志级别1、基础设置2、…

golang-基础知识(流程控制)

1 条件判断if和switch 所有的编程语言都有这个if&#xff0c;表示如果满足条件就做某事&#xff0c;不满足就做另一件事&#xff0c;go中的if判断和其它语言的区别主要有以下两点 1. go里面if条件判断不需要括号 2. go的条件判断语句中允许声明一个变量&#xff0c;这个变量…

FPGA-UART串口接收模块的理解

UART串口接收模块 背景 在之前就有写过关于串口模块的文章——《串口RS232的学习》。工作后很多项目都会用到串口模块&#xff0c;又来重新理解一下FPGA串口接收的代码思路。 关于串口相关的参数&#xff0c;以及在文章《串口RS232的学习》中已有详细的描述&#xff0c;这里就…