Windows高级编程学习笔记(二)

第三章 进程

发现这本书的文字很简练,知识点突出,而且翻译的基本没有拗口的地方,是本好书,(^o^)/~

下面进入正题。

关于内存映射

Windows内存管理的分页机制在微机原理课程中有提到,后面的章节也有相关内容。这里提前写是怕以后忘了写出来。
一直不明白”内存映射“是怎么一回事,如很多编程资料中都会说,DLL在内存中只有一份,只是映射到不同进程的地址空间中,但是具体怎么映射的让人只知其一不知其二。还有后面的内存映射文件到底是怎么映射的?使用分页机制可以解释。所谓分页机制就是使用高速缓冲区制作一个表,先将线性地址分解成各个部分,然后分级查找到此线性地址所对应的内存页面(通常4KB)。而这个表的内容是由操作系统来管理的。那么要实现共享DLL所在内存或者其他内存,只需要把相应的页面地址填入进程对应的高速缓冲区中即可,这是基本原理,其中,不是页面对其的内存是怎么处理的这些细节问题只有通过继续学习才能知道,虽然说对于编写程序没什么影响,但是作为一名C/C++程序员,尽可能多地了解更多的底层知识总不是件坏事。

知识点汇总

  • Win32的进程是惰性的。每个进程必须拥有一个主线程(primary thread)才能工作。换句话说,Windows在创建一个进程时,同时会为此进程创建一个线程。这种处理方式把进程和线程完全分开了,能运行的只有线程,进程是线程的更大一级单位,或者说是载体。在Linux中,创建的进程是可以直接运行的,相当于主线程,这种处理方式将进程和线程区分得不是非常清楚。

  • WinMain函数不是GUI程序的入口点,它是由C运行时启动函数调用的。这么说又涉及到什么是运行时启动函数的问题。下面是我的理解:C语言编程中的main()函数大家都知道吧,这个就是入口函数。不管是运行CUI还是GUI程序,都是先进入main()函数。如果是GUI程序,main()函数会先做一些处理(初始化一些变量),然后调用WinMain函数。

  • 了解WinMain的几个参数。

    hInstance:进程的实例句柄hInstance是一个地址,指向应用程序加载到内存时的起始地址(在此程序的线性地址空间)。它和hModule是一样的,之所以存在两个称呼,是由于历史原因在16位windows中遗留下来的称呼,或者说为了保持兼容性而保留的。在测试时发现每次运行程序时这个值都会不一样。
    相关函数(32位windows下):

    • GetModuleHandle(LPCTSTR lpszModule):获取已加载的EXE或DLL文件的起始地址。参数是模块名称,注意查找范围仅限于当前进程。如果为NULL,则返回此程序EXE在内存中的起始地址。另外,如果在DLL中调用此函数,同时参数为NULL,返回的仍然是调用进程的地址,而不是DLL的基地址,和上面的结论相同。

    hPrevInstance:在16位的windows下表示此应用程序的前一个运行实例,在32位下没有此意义,只是为了兼容。

    lpszCmdLine:启动参数。非常特别需要注意的是,它总一个ANSI字符串。当你CreateProcess时,传入的非空命令行参数也必须为ANSI字符串,否则应用程序会出错或者崩溃。
    这个lpszCmdLine和CUI的main函数的命令行参数不一样,第一个参数(可执行文件路径)被main除去之后传入了WinMain。
    相关函数(32bit):

    • LPTSTR GetCommandLine(VOID):获取命令行指针,有ANSI版和UINCODE版。
    • LPWSTR CommandLineToArgvW(LPWSTR cmdLine, LPINT pArgc):将宽字符版的命令行参数转换成参数数组,数组个数保存在*pArgc中。

    还可以使用全局变量来访问命令行参数:_argv(原始的ANSI字符串数组),_argc。不过如果WinMain是在mian()函数中调用的,那么自然可以访问mian()函数的两个参数:argc, argv。

  • 进程的环境变量。它就是一组全局字符串,由系统设置,这个字符串在注册表中可以找到。子进程继承自父进程,但是进程间环境变量内存区是独立的。

    相关函数:

    • GetEnvironmentVariable()
    • SetEnvironmentVaribale()
  • 进程的驱动器目录可以通过环境变量来读写。

    相关函数:
    SetCurrentDirectory()
    GetFullPathName()

  • 操作系统个版本。

    相关函数:
    DWORD GetVersionEx(LPOSVERSIONINFO lpVersionInformation):

  • 重要函数:CreateProcess()
    上一段代码:

// CreateProcess.cpp : 定义控制台应用程序的入口点。#include "stdafx.h"
#include "windows.h"
int _tmain(int argc, _TCHAR* argv[])
{//wprintf(L"%s\n", (const wchar_t*)argv[0]);STARTUPINFOA si; // 这个结构体有些成员挺有用,还有专门针对开发屏幕保护程序的标志,另外WinMian()函数的nCmdShow也是通过此结构体传递的ZeroMemory(&si, sizeof(si));si.cb = sizeof(si);SECURITY_ATTRIBUTES saProcess;SECURITY_ATTRIBUTES saThread;saProcess.nLength = sizeof(saProcess);saProcess.lpSecurityDescriptor = NULL;saProcess.bInheritHandle = TRUE; // 这是设置某个内核对象的可继承性saThread.nLength = sizeof(saThread);saThread.lpSecurityDescriptor = NULL;saThread.bInheritHandle = FALSE; // 含义同saProcessPROCESS_INFORMATION piProcess;BOOL res = CreateProcessA(NULL, // 如果非空,则只在当前目录下查找"notepad.exe", // 必须为ANSI字符串&saProcess,&saThread,false, // 这是针对进程这个特殊的内核对象独有的,因为创建进程时需要创建内核句柄表,这就存在是否继承父进程的问题。0,NULL, // 指向新的环境变量字符串区,为NULL,则使用默认的、继承自父进程的环境变量NULL, // 设置当前驱动器和工作路径(必须包含盘符)。为NULL,则使用和父进程相同的驱动器和工作路径。&si,&piProcess // 只有它是输出,不能NULL,否则创建错误,错误码为87:参数错误);if (FALSE == res){printf("创建新进程出错,错误码:%d", GetLastError());}return 0;
}
  • 结束进程

    三种方法:

    • 主动调用ExitProcess()函数。

    • 外部调用TerminateProcess()函数,不推荐使用,会导致资源不能被释放以及DLL推出时执行的操作没有被执行等问题。

    • 进程中所有线程都结束,系统会自动终止进程。特别的,如果主线程是自然返回的话,系统会调用ExitProcess()自动结束进程,此时可能还有线程正在执行,它们都将被终止。如果在主线程结束时想保持其他线程继续运行,那么需要主线程主动调用ExitThread()终止自己。

    进程结束,不影响子进程。
    使用WaitForSingleObject()实现阻塞调用进程直到子进程运行结束。
    创建完全分离的子进程的要点是:释放所有本进程中与子进程相关的句柄。

  • 查看进程退出代码或者查看进程是否终结:GetExitCodeProcess()。

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

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

相关文章

【转】1.5异步编程:.NET4.X 数据并行

任务并行库 (TPL) 是 .NET Framework 4的 System.Threading 和 System.Threading.Tasks 命名空间中的一组公共类型和 API。TPL的目的在于简化向应用程序中添加并行性和并发性的过程,从而提高开发人员的工作效率。TPL会动态地按比例调节并发程度,以便最有…

idea全局搜索搜不全的BUG

搜不全真是坑坏我了,修改业务后,差点就卷铺盖走人了… 修改配置 打开help -> Find Action 输入registry后搜索(点击框内任意一行后,直接输入就是搜索) page.size 将100的值改大,一步到位100000

Windows高级编程学习笔记(三)

第四章 线程 知识要点 每向系统获取一个句柄,会使相应对象的引用计数加1。而GetCurrentProcess()函数返回的是一个伪句柄,也就是不增加引用计数,相当于赋值拷贝。对应于线程,有GetCurrentThread(),情况同GetCurrentPr…

【转】1.6异步编程:IAsyncResult异步编程模型 (APM)

传送门:异步编程系列目录…… 大部分开发人员,在开发多线程应用程序时,都是使用ThreadPool的QueueUserWorkItem方法来发起一次简单的异步操作。然而,这个技术存在许多限制。最大的问题是没有一个内建的机制让你知道操作在什么时候…

python图形模块_使用Python图形模块:有没有办法将当前窗口保存为图像?

我正在使用pythongraphics模块。我要做的是将当前窗口保存为图像。在模块中,有一个选项可以将“图像”另存为图像(图像.保存()). 但这并没有帮助,因为它只是保存一个已经加载的图像。或者,如果你像我一样加载一个空白图像,希望在上…

Spark worker内存不足导致任务失败,报错Likely due to containers exceeding thresholds, or network issues

报错: Lost executor 33 on xx.xx.xx.152: Remote RPC client disassociated. Likely due to containers exceeding thresholds, or network issues. Check driver logs for WARN messages. 原因: 由于spark某节点可用内存不足导致整个任务失败,在执行…

Qt:程序异常退出

现象 编译成功,但是运行时崩溃并在控制台输出:“程序异常错误”。 可能原因 查阅资料,原因可能是库错误。 最终解决方法 的确是库错误,原因是编译库的Qt版本和使用该库的Qt程序对应的Qt版本不相同。需要使用相同版本的Qt来生…

python用什么系统好_10分钟用python搭建一个超好用的CMDB系统

{{ message }}new Vue({ el: #app, data: { message: Hello Vue.js! } })

【转】1.7异步编程:基于事件的异步编程模式(EAP)

传送门:异步编程系列目录…… 上一篇,我给大家介绍了“.NET1.0 IAsyncResult异步编程模型(APM)”,通过Begin*** 开启操作并返回IAsyncResult对象,使用 End*** 方法来结束操作,通过回调方法来做异步操作后其它事项。然…

C安全编程知识点

1、因为非零即为真,不要用下面的语句来判断 if (TRUE condition) 要改写成 if (condition) 判断条件为假也一样要用: if (!condition)

python怎样定义一个数组_python如何建立全零数组

语句格式: numpy.zeros(shape, dtypefloat, orderC) 参数说明: shape:整型或元素为整型的序列,表示生成的新数组的shape,如(2,3)或 2。 dtype:生成数组的数据格式,如numpy.int8。默认…

【转】1.8异步编程:.NET 4.5 基于任务的异步编程模型(TAP)

传送门:异步编程系列目录…… 最近我为大家陆续介绍了“IAsyncResult异步编程模型 (APM)”和“基于事件的异步编程模式(EAP)”两种异步编程模型。在.NET4.0 中Microsoft又为我们引入了新的异步编程模型“基于任务的异步编程模型(TAP)”,并且推荐我们在开…

Hbase模糊查询优化 - 并发查询

HBase模糊查询优化 - 并发查询 HBase查询优化续集,继上次优化后查询速度还是很慢, 这次优化我们使用并发查询,查询HBase库里的各region拆分情况,然后对查询的rowkey切分成多段,每一段单独去不同的region中查询&#x…

Qt: 找不到Qt5Widgets.lib

在静态编译的时候,提示错误: error: dependent ‘D:\IDE\Qt\5.4.2-mingw32-rel-static\5.4.2-mingw32-rel-static\lib\Qt5Widgets.lib 去目录下看了下,全部是libxxxxx.a文件,是linux的库文件。但是之前编译是正常的,这…

python3读写excel文件_python3 循环读取excel文件并写入json操作

文件内容:excel内容:代码: import xlrd import json import operator def read_xlsx(filename): # 打开excel文件 data1 xlrd.open_workbook(filename) # 读取第一个工作表 table data1.sheets()[0] # 统计行数 n_rows table.nrows data …

Qt:error LNK2038: 检测到“_MSC_VER”的不匹配项: 值“1600”不匹配值“1800

Visual Studio 2013生成Qt项目时报错。网上搜说是更改平台工具集,试了没用。退一步说我就是需要使用vs2013,改成其他的会不符合项目需求。于是打开了项目文件.sln,如下: 才发现目标工程的Qt版本是5.7.0,vs2013里面设置…

JAVA程序绑定到指定的CPU核上

由于服务器上某几个核被C程序绑定了&#xff0c;我们的java程序有的线程会使用到&#xff0c;导致C程序丢包异常&#xff0c;所以需要将JAVA程序绑定到指定的CPU核上 1.命令介绍 1.taskset命令 taskset -c <cpu核编号> <pid> #可以指定进程绑定到哪个cpu核上2.t…

【转】URN_URI_URL详解

URI&#xff0c;Uniform Resource Identifier&#xff0c;统一资源标识符。 URN&#xff0c;Uniform Resource Name&#xff0c;统一资源命名 URL&#xff0c;Uniform Resource Location&#xff0c;统一资源定位符。 URI 简单来理解就是标识/定义了一个资源&#xff0c;而 URL…

python生成json_生成动态嵌套JSON对象和数组-python - python

正如问题所解释的那样&#xff0c;我一直在尝试生成嵌套的JSON对象。在这种情况下&#xff0c;我有for循环从字典dic中获取数据。下面是代码&#xff1a; f open("test_json.txt", w) flag False temp "" start "{\n\t\"filename\"&quo…

彻底弄懂Qt的编码(汉字乱码问题及相关函数作用)

测试1 新建test工程用于测试&#xff0c;main.c文件内容如下&#xff1a; #include <QCoreApplication> #include <QDebug>int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);QString str_hanzi("百度"); // 汉字QString str_ascii(&…