Windows核心编程<读书笔记四> 进程的概念

【文起】豆子爱蟹儿,没有你,我不可能每天坚持下去,为了你和我们的爱奋斗 

进程

1、  进程和线程:

进程通常被定义为一个正在运行的程序实例。由两个部分组成:

*操作系统用来管理进程的内核对象;

*地址空间,包含所有可执行模块或DLL模块的代码和数据,还包含动态内存分配的空间。

进程是不活泼的,必须拥有线程来执行包含在进程的地址空间中的代码。创建一个进程时,系统将会自动创建一个线程,称为主线程。该线程可以再创建其他线程。

2、  Windows的应用程序:

Windows支持两种应用程序:1、基于图形用户界面(GUI)的应用程序;2、基于控制台用户界面(CUI)的应用程序。

CUI链接程序开关是/SUBSYSTEM:CONDOLE;GUI链接程序开关是:/SUBSYSTEM:WINDOWS

Windows应用程序都有一个接入点函数,也就是我们通常称为的main函数。

int WINAPI WinMain(HINSTANCE hinstExe,HINSTANCE,PSTR pszCmdLine,int nCmdShow);

int WINAPI wWinMain(HINSTANCE hinstExe,HINSTANCE,PWSTR pszCmdLine,int nCmdShow);

int __cdel main(int argc,char *argv[], char *envp[]);

int __cdecl wmain(int argc,wchar_t *argv[],wchar_t *envp[]);

 

如果链接程序开关为/SUBSYSTEM:CONDOLE,那么链接程序希望找到一个main或者wmian开头的程序,如果没有找到,那么就会返回一条“未转换外部符号”的信息;同样,如果链接程序开关为/SUBSYSTEM:WINDOWS,那么链接程序希望找到一个WinMain或者wWinMain开头的程序。

当然有一个最好的办法来解决链接程序开关,那就是全部删除链接程序开关,这样系统会去寻找4个接入点函数,然后自动确定使用哪一个。

程序执行的步骤:

A、 检索指向新进程的完整命令行的指针;

B、 检索指向新进程的环境变量的指针;

C、 对C/C++运行期的全局变量进程初始化;

D、 对C运行期间内存单元分配函数和其他底层输入/输出例程使用的内存栈进程初始化;

E、  为所有全局和静态C++类对象调用构造函数

F、  进入接入点函数,执行、退出

G、 调用由_onexit函数的调用而注册的任何函数

H、 为所有全局和静态C++类对象调用析构函数;

I、   调用操作系统的ExitProcess函数

3、  进程的实例句柄

3.1使用GetModuleHandle函数,将返回可执行文件或DLL文件加载到进程的地址空间时所用的句柄/基地址 HMODULE GetModuleHandle(PCTSTR pszModule);

3.2修改环境变量

3.3当前目录:如GetCurrentDirectory(DWORD cchCurDir,PTSTR pszCurDir);

BOOL SetCurrentDirectory(PCTSTR pszCurDir);

3.4系统版本号:

举例检查一个系统是Windows xp

#include <windows.h>

 

 

int _tmain(int argc, _TCHAR* argv[])

{

    OSVERSIONINFOEX osver = {0};

    osver.dwOSVersionInfoSize = sizeof(osver);

    osver.dwMajorVersion = 5;

    osver.dwMinorVersion = 1;

    osver.dwPlatformId =VER_PLATFORM_WIN32_NT;

     DWORDLONG dwlConditionMask = 0;

    VER_SET_CONDITION(dwlConditionMask,VER_MAJORVERSION,VER_EQUAL);

    VER_SET_CONDITION(dwlConditionMask,VER_MINORVERSION,VER_EQUAL);

    VER_SET_CONDITION(dwlConditionMask,VER_PLATFORMID,VER_EQUAL);

     if (VerifyVersionInfo(&osver,VER_MAJORVERSION|VER_MINORVERSION|VER_PLATFORMID,dwlConditionMask))

    {
       printf("The host system is Windows xp");
    } 

    else

    {
       printf("The host system is not Windows xp");
    }

 
    /* 调用另一个函数来看看*/

    GetVersionEx((LPOSVERSIONINFOW)&osver);

    printf("MajorVersion = %u,MinorVersion = %u",

       osver.dwMajorVersion,osver.dwMinorVersion);

    return 0;
}

 

4、  CreateProcess函数

当一个线程调用该函数时,系统会自动生成一个进程内核对象,初始计数为1.然后系统为该进程创建一个虚拟地址空间,将可执行文件或者DLL文件的代码、数据拷入,系统会为该进程的主线程创建一个线程内核对象,最终调用main函数开始执行。

CreateProcess函数参数所需要注意的地方:

4.1参数pszCommandLine必须是一个和修改的参数。虽然函数不会修改,但是不能传入只读的。如

STARTUPINFO si = {sizeof(si)};

  PROCESS_INFORMATION pi;

CreateProcess(NULL,_T("NOTEPAD"),NULL,NULL,FALSE,0,NULL,NULL,&si,&pi);

就会报错,而这样操作,就可以通过

TCHAR szCommandLine[] = _T("NOTEPAD");

CreateProcess(NULL,szCommandLine,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi);

5、  进程终止

5.1主线程的进入点函数返回;(最好使用这个方法)

Ø  该线程创建的任何C++对象将能使用它们的析构函数正确的撤销;

Ø  操作系统能正确的释放该线程的堆栈使用的内存;

Ø  系统将进程的退出代码设置为进入点函数的返回值;(调用ExitProcess)

Ø  系统将进程内核对象的返回值减一

5.2进程中的一个线程调用ExitProcess函数;(避免使用)

与5.1相比,跳过了析构函数的撤销等,直接调用ExitProcess函数。

所以这种情况C++的类对象没有机会去调用析构函数。(如果使用VS2008的话,会发现全局变量还是被释放了,只有局部变量没有释放,这个我会再总结一份)

5.3另一个进程中的线程,调用TerminateProcess函数;(避免使用)

           该函数是一个异步函数,也就是说,它会通知操作系统,想要终止运行一个进程,但是这个函数无法知道也无法保证进程是否已经终止运行。如果想要知道,必须调用WaitForSingleObject函数。

5.4进程中的所有线程自行终止运行。(几乎从未发生)

 

 【文尾】如果文章对您有帮助,请留下对我和蟹儿的祝福,谢谢~~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值