VC++中进程与多进程管理的方法
发布时间:2008/8/23 0:00:00 访问次数:656
进程是当前操作系统下一个被加载到内存的、正在运行的应用程序的实例。每一个进程都是由内核对象和地址空间所组成的,内核对象可以让系统在其内存放有关进程的统计信息并使系统能够以此来管理进程,而地址空间则包括了所有程序模块的代码和数据以及线程堆栈、堆分配空间等动态分配的空间。进程仅仅是一个存在,是不能独自完成任何操作的,必须拥有至少一个在其环境下运行的线程,并由其负责执行在进程地址空间内的代码。在进程启动的同时即同时启动了一个线程,该线程被称作主线程或是执行线程,由此线程可以继续创建子线程。如果主线程退出,那么进程也就没有存在的可能了,系统将自动撤消该进程并完成对其地址空间的释放。
加载到进程地址空间的每一个可执行文件或动态链接库文件的映象都会被分配一个与之相关联的全局唯一的实例句柄(hinstance)。该实例句柄实际是一个记录有进程加载位置的基本内存地址。进程的实例句柄在程序入口函数winmain()中通过第一个参数hinstance hinstexe传递,其实际值即为进程所使用的基本地址空间的地址。对于vc++链接程序所链接产生的程序,其默认的基本地址空间地址为0x00400000,如没有必要一般不要修改该值。在程序中,可以通过getmodulehandle()函数得到指定模块所使用的基本地址空间。
子进程的创建
进程的创建通过createprocess()函数来实现,createprocess()通过创建一个新的进程及在其地址空间内运行的主线程来启动并运行一个新的程序。具体的,在执行createprocess()函数时,首先由操作系统负责创建一个进程内核对象,初始化计数为1,并立即为新进程创建一块虚拟地址空间。随后将可执行文件或其他任何必要的动态链接库文件的代码和数据装载到该地址空间中。在创建主线程时,也是首先由系统负责创建一个线程内核对象,并初始化为1。最后启动主线程并执行进程的入口函数winmain(),完成对进程和执行线程的创建。
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 // 指向进程信息结构的指针
);
在程序设计时,某一个具体的功能模块可以通过函数或是线程等不同的形式来实现。对于同一进程而言,这些函数、线程都是存在于同一个地址空间下的,而且在执行时,大多只对与其相关的一些数据进行处理。如果算法存在某种错误,将有可能破坏与其同处一个地址空间的其他一些重要内容,这将造成比较严重的后果。为保护地址空间中的内容可以考虑将那些需要对地址空间中的数据进行访问的操作部分放到另外一个进程的地址空间中运行,并且只允许其访问原进程地址空间中的相关数据。具体的,可在进程中通过createprocess()函数去创建一个子进程,子进程在全部处理过程中只对父进程地址空间中的相关数据进行访问,从而可以保护父进程地址空间中与当前子进程执行任务无关的全部数据。对于这种情况,子进程所体现出来的作用同函数和线程比较相似,可以看成是父进程在运行期间的一个过程。为此,需要由父进程来掌握子进程的启动、执行和退出。下面这段代码即展示了此过程:
// 临时变量
cstring scommandline;
char cwindowsdirectory[max_path];
char ccommandline[max_path];
dword dwexitcode;
process_information pi;
startupinfo si = {sizeof(si)};
// 得到windows目录
getwindowsdirectory(cwindowsdirectory, max_path);
// 启动"记事本"程序的命令行
scommandline = cstring(cwindowsdirectory) + "\\notepad.exe";
::strcpy(ccommandline, scommandline);
// 启动"记事本"作为子进程
bool ret = createprocess(null, ccommandline, null, null, false, 0, null, null, &si, pi);
if (ret) {
// 关闭子进程的主线程句柄
closehandle(pi.hthread);
// 等待子进程的退出
waitforsingleobject(pi.hprocess, infinite);
// 获取子进程的退出码
getexitcodeprocess(pi.hprocess, &dwexitcode);
// 关闭子进程句柄
close
进程是当前操作系统下一个被加载到内存的、正在运行的应用程序的实例。每一个进程都是由内核对象和地址空间所组成的,内核对象可以让系统在其内存放有关进程的统计信息并使系统能够以此来管理进程,而地址空间则包括了所有程序模块的代码和数据以及线程堆栈、堆分配空间等动态分配的空间。进程仅仅是一个存在,是不能独自完成任何操作的,必须拥有至少一个在其环境下运行的线程,并由其负责执行在进程地址空间内的代码。在进程启动的同时即同时启动了一个线程,该线程被称作主线程或是执行线程,由此线程可以继续创建子线程。如果主线程退出,那么进程也就没有存在的可能了,系统将自动撤消该进程并完成对其地址空间的释放。
加载到进程地址空间的每一个可执行文件或动态链接库文件的映象都会被分配一个与之相关联的全局唯一的实例句柄(hinstance)。该实例句柄实际是一个记录有进程加载位置的基本内存地址。进程的实例句柄在程序入口函数winmain()中通过第一个参数hinstance hinstexe传递,其实际值即为进程所使用的基本地址空间的地址。对于vc++链接程序所链接产生的程序,其默认的基本地址空间地址为0x00400000,如没有必要一般不要修改该值。在程序中,可以通过getmodulehandle()函数得到指定模块所使用的基本地址空间。
子进程的创建
进程的创建通过createprocess()函数来实现,createprocess()通过创建一个新的进程及在其地址空间内运行的主线程来启动并运行一个新的程序。具体的,在执行createprocess()函数时,首先由操作系统负责创建一个进程内核对象,初始化计数为1,并立即为新进程创建一块虚拟地址空间。随后将可执行文件或其他任何必要的动态链接库文件的代码和数据装载到该地址空间中。在创建主线程时,也是首先由系统负责创建一个线程内核对象,并初始化为1。最后启动主线程并执行进程的入口函数winmain(),完成对进程和执行线程的创建。
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 // 指向进程信息结构的指针
);
在程序设计时,某一个具体的功能模块可以通过函数或是线程等不同的形式来实现。对于同一进程而言,这些函数、线程都是存在于同一个地址空间下的,而且在执行时,大多只对与其相关的一些数据进行处理。如果算法存在某种错误,将有可能破坏与其同处一个地址空间的其他一些重要内容,这将造成比较严重的后果。为保护地址空间中的内容可以考虑将那些需要对地址空间中的数据进行访问的操作部分放到另外一个进程的地址空间中运行,并且只允许其访问原进程地址空间中的相关数据。具体的,可在进程中通过createprocess()函数去创建一个子进程,子进程在全部处理过程中只对父进程地址空间中的相关数据进行访问,从而可以保护父进程地址空间中与当前子进程执行任务无关的全部数据。对于这种情况,子进程所体现出来的作用同函数和线程比较相似,可以看成是父进程在运行期间的一个过程。为此,需要由父进程来掌握子进程的启动、执行和退出。下面这段代码即展示了此过程:
// 临时变量
cstring scommandline;
char cwindowsdirectory[max_path];
char ccommandline[max_path];
dword dwexitcode;
process_information pi;
startupinfo si = {sizeof(si)};
// 得到windows目录
getwindowsdirectory(cwindowsdirectory, max_path);
// 启动"记事本"程序的命令行
scommandline = cstring(cwindowsdirectory) + "\\notepad.exe";
::strcpy(ccommandline, scommandline);
// 启动"记事本"作为子进程
bool ret = createprocess(null, ccommandline, null, null, false, 0, null, null, &si, pi);
if (ret) {
// 关闭子进程的主线程句柄
closehandle(pi.hthread);
// 等待子进程的退出
waitforsingleobject(pi.hprocess, infinite);
// 获取子进程的退出码
getexitcodeprocess(pi.hprocess, &dwexitcode);
// 关闭子进程句柄
close
上一篇:EDA技术应用与发展之管窥