• 第四章 进程


    //1.
    一般将进程定义为一个正在运行的程序的一个实例,由两个部分组成:
    (A):一个内核对象,操作系统利用内核对象来管理进程。内核对象也是系统保存进程统计信息的地方
    (B):一个地址空间,包含所有可执行文件或DLL模块的代码和数据
    
    //2.
    进程要做任何事情,都必须让一个线程在其上下文中运行,该线程负责执行进程地址空间的代码,
    当系统创建进程的时候,会自动为其创建一个主线程
    操作系统会以轮询的方式为每个线程分配时间片供其运行,在多线程环境下,多个线程可以同时运行
    
    //3. 关于入口函数
    (A):Windows支持两种类型的应用程序:GUI程序和CUI程序
    (B):前者为图像用户界面(Graphical User Interface),后者为控制台用户界面(Console User Interface)
    (C):前者的连接器开关是 /SUBSYSTEM:WINDOWS 后者是 /SUBSYSTEM:CONSOLE
    (D):Windows应用程序必须有一个入口点函数,应用程序开始运行时,这个函数会被调用
    (E):GUI程序对应入口点函数为 WinMain ,CUI程序对应入口点函数为 main
    (F):操作系统实际并不调用我们所写的入口点函数,相反他会调用由C/C++运行库实现并在链接时使用-enter:命令行选项来设置一个C/C++运行时启动函数
    (G):上述函数将初始化C/C++运行库,使得我们能调用 malloc 等函数,还确保在我们的代码开始执行前,我们声明的全局变量和全局静态C++对象被正确的构造
    (H):如下命令也可以用于设置入口点函数:#pragma comment(linker, "/entry:"Fun"")
    (I):在vs2010中使用自定义入口函数并有定义全局对象则会有警告 : warning LNK4210: 存在 .CRT 节;可能有未处理的静态初始值设定项或结束符
    
    //4. 启动函数用途
    (A):获取指向新进程的完整命令行的指针
    (B):获取指向新进程的环境变量的一个指针
    (C):初始化C/C++运行库的全局变量,如果包含了 stdlib.h 则我们的代码就可以访问这些变量了
    (D):初始化C运行库内存分配函数和其他底层I/O使用的堆
    (E):调用所有全局C++类对象的构造函数
    备注:自定义入口函数并不完全具备上述功能
    
    //5.
    如需访问进程的环境变量,可以使用如下形式:
    int _tmain(int argc, _TCHAR* argv[], _TCHAR* pStr[])
    则 pStr 中将存储环境变量
    
    //6.
    入口点函数返回后,启动函数将调用C运行库函数 exit ,向其传递返回值,此函数执行以下任务:
    (A):调用 _onexit 函数调用所注册的任何一个函数
    (B):调用所有全局C++类对象的析构函数
    (C):在 DEBUG 生成中,如果设置了 _CRTDBG_LEAK_CHECK_DF 标志,就通过调用 _CrtDumpMemoryLeaks 函数来生成内存泄漏报告
    (D):调用操作系统的 ExitProcess 函数,向其传递返回值,这回导致系统杀死我们的进程,并设置退出代码
    备注: 定义在头文件 crtdbg.h 中的 _CrtDumpMemoryLeaks 函数,会检测到运行到此函数为止的所有未释放的内存并打印
    
    //7.
    加载到进程地址空间的每一个可执行文件或者DLL文件都被赋予一个独一无二的实例句柄,可执行文件的实例句柄被 WinMain 的第一个参数传入
    
    //8.
    (A):每个进程都有一个与他关联的环境块,这是在进程地址空间分配的一块内存,其中的字符串的第一部分是一个环境变量的名称后接一个等号,
    	等号后是希望赋予给变量的值(备注:用=进行分割,所以空格在环境变量的值中是有意义的)
    (B):用户可以在环境变量对话框中修改环境变量,为了使得这些改动生效,必须注销后重新登录
    (C):通常子进程会继承一组环境变量,这些环境变量与父进程的环境变量相同。父进程可以控制继承的过程
    (D):子进程继承环境变量并不会与父进程共享同一个环境块,所以子进程修改了自己环境块中的环境变量并不会影响父进程
    	SetEnvironmentVariable GetEnvironmentVariable 用户改变与获取与进程绑定的环境变量,且更改不会影响其他进程
    	https://msdn.microsoft.com/en-us/library/windows/desktop/ms686206(v=vs.85).aspx
    (F):许多字符串的内部包含了可替换字符串,比如注册表的某个地方发现了下面这个字符:%s%1234 则两个%之间的这一部分就是一个可替换字符串,
    	这种情况下,对应环境字符串s的值就放在这里, ExpandEnvironmentStrings 可以执行以上转换
    const int nLenC = 1024;
    TCHAR wBuff[nLenC] = {};
    GetEnvironmentVariable(TEXT("szn"), wBuff, nLenC);				//wBuff = 0x0015efe4 "big"
    
    memset(wBuff, 0, sizeof wBuff);
    GetEnvironmentVariable(TEXT("%szn%\Hello"), wBuff, nLenC);		//wBuff = 0x0038ef98 "HelloWord"
    
    memset(wBuff, 0, sizeof wBuff);
    ExpandEnvironmentStrings(TEXT("%szn%\Hello"), wBuff, nLenC);	//wBuff = 0x0035f4f0 "bigHello"
    
    //9.
    
    GetCurrentDirectory	SetCurrentDirectory 用于获取与设置当前程序目录
    
    //10.
    GetVersionEx 用于获取系统信息
    
    //11.
    利用 CreateProcess 创建一个进程
    https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx
    
    //12.
    终止进程:
    (A):主线程入口点函数返回(强烈建议)
    (B):进程中的一个线程主动调用 ExitProcess (强烈不推荐)
    (C):另一个进程的线程调用 TerminateProcess (强烈不推荐)
    (D):进程中的所有线程自然死亡 (几乎不会发生)
    
    (A):
    设计一个应用程序的时候,应该保证只有主线程的入口函数返回之后,这个应用进程才终止。这样才能保证主线程所有资源都被清理
    让主线程的入口点函数返回,可以保证如下操作被正确执行:
    (a):该线程创建的任何C++对象都将由这些对象的析构函数正确销毁
    (b):操作系统正确的释放线程栈使用的内存
    (c):系统将进程的退出代码(在内核对象中维护)设为入口点函数的返回值
    (d):系统递减进程内核对象的使用计数
    
    (B):
    (a):当主线程的入口函数返回时,会返回到C/C++运行库启动代码,后者将正确清理进程使用的全部C运行时资源。释放了C运行时资源之后,
    	C运行时启动代码将显示调用 ExitProcess ,并将入口函数返回值传给他。所以当主线程入口点函数返回,就会终止整个进程
    (b:)如果入口点函数中调用 ExitThread ,应用程序的主线程将停止执行,但只要进程中仍有其他线程运行,进程就不会终止
    (c):调用 ExitProcess 或 ExitThread 会导致进程或线程直接终止运行,就操作系统而言,这样做不会有什么问题,进程或线程的资源都会被释放,
    	不过对于C/C++应用程序而言应避免调用这些函数,因为C/C++运行库也许也不能执行正确的清理工作,比如C++类的析构函数可能不会被调用
    
    (C):
    (a):使用 TerminateProcess 也可以终止一个进程,任何一个线程都可以使用此函数来干掉另一个进程或自身进程。
    (b):使用 TerminateProcess 时,被终止的进程得不到自己要被干掉的通知,应用程序不能正确的清理,也不能防止自己被干掉(除非通过正常的安全机制)
    (c):虽然进程没有机会自己执行清理工作,但操作系统会在进程终止之后彻底清理,确保不会泄露任何操作系统资源
    (d):一旦进程终止(不管如何终止),系统会保证不留他的任何部分。绝对没有任何办法知道那个进程是否运行过。进程在终止后绝对不会泄露任何东西
    (e):TerminateProcess 此函数是异步的
    
    一个进程终止时,系统一次执行以下操作:
    (A):终止进程中遗留的线程
    (B):释放所有用户对象与GDI对象
    (C):进程的退出代码从 STILL_ACTIVE 变为传给 ExitProcess 或 TerminateProcess 函数的代码
    (D):进程的内核对象的状态变为已触发
    (E):进程对象的使用计数被减一
    
    GetExitCodeProcess GetExitCodeThread 可以获取进程或线程退出代码
    

      

  • 相关阅读:
    maven核心概念--生命周期
    maven核心概念--插件和目标
    TDD入门demo
    第一个简单的maven项目
    java -cp用法
    TDD最佳实践
    自定义测试规则
    自定义测试执行器
    junit3对比junit4
    Junit4X系列--hamcrest的使用
  • 原文地址:https://www.cnblogs.com/szn409/p/8366102.html
Copyright © 2020-2023  润新知