先来明确下概念:
进程和线程:
进程:进程是一个正在运行的程序,它拥有自己的虚拟地址空间,用有自己的代码,数据和其他系统资源,一个进程也包含了。一个或者多个运行在此进程内的线程。
线程:线程是进程内执行代码的独立实体。
总结下:进程和线程的关系是,进程用有线程。记得上操作系统的时候说区别时提到过,进程是系统分配资源的单位,线程是系统调度的单位。线程的引入了为了减少系统在进行进程调度的时候,减少进程上下文切换代价而引入的。操作系统创建进程后,会创建一个线程执行进程中的代码,这个线程称为主线程,由这个主线程创建的线程称为该进程的辅助线程。
程序启动:
上课的时候老师说程序的入口函数是main函数。但现在得改变观念了。
操作系统并不是真正的调用main函数,而是去调用C/C++运行期启动函数,这函数去会初始化C/C++运行期库。C/C++运行期启动函数会调用程序入口函数main。
看下win32程序启动过程:系统调用CreateProcess函数(创建进程内核对象)-------->创建主线程(执行C/C++运行期启动代码)----------->C/C++运行期启动代码(调用main函数)--------------->main函数(程序执行)
缺少main函数会出现如下错误:
父进程传递给子进程的数据结构:STARTUPINFO:
STARTUPINFO是结构体类型。由父进程传递给子进程。子进程可以通过GetStartupInfo函数来获取父进程传递给它的信息。
函数:void GetStartupInfo(LPSTARTUPINFO lpStartupInfo)//lp表示指针类型。
调用GetStartupInfo函数时我们要先定义一个STARTUPINFO的结构体对象,其中我们需要使用sizeof来获得其自身的大小:
STARTUPINFO si = {sizeof(si)};网上似乎有同学问改成si.cb =sizeof(si);这样是不行的。因为这时候si这个结构体对象还未定义好,所以不能去地址,取变量。
可以改成:STRARTUPINFO = si; si.cb = sizeof(si);但是这样不能对STARTUPINFO的其它参数默认赋值;
可以:STARTUPINFO si = {0}; si.cb = sizeof(si); 但是这样岂不是多此一举。
CreateProcess函数:
创建进程的时候调用CreateProcess函数。其函数原型为:
CreateProcess(
LPCSTR lpApplicationName,//可执行文件的名称
LPSTR lpCommandLine,//指定传递给执行模块的参数
LPSECURITY_ATTRIBUTES lpProcessAttributes, //进程安全性,NULL表示默认安全属性
LRSECURITY_ATTRIBUTES lpThreadAttributes,//线程安全性,NULL表示默认安全属性
BOOL bInheritHandles, //指定了当前进程可以被继承句柄是否可以被新进程继续
DWORD dwCreationFlags, //指定了新进程的优先级和其他创建标识
LPVOID lpEnvironment, //指定了新进程使用的环境变量
LPCSTR lpCurrentDirectory, //进程使用的当前目录
LPSTARTUPINFO lpStartupInfo, //指定了新进程中主窗口的位置,大小和标准句柄等。
LPPROCESS_INFORMATION lpProcessInformation // 返回新进程的标识信息
);
创建进程的例子:(书上的)
//创建进程 #include <stdio.h> #include<windows.h> int main(int argc, char *argv[]) { char szCommandLine[]="cmd"; STARTUPINFO si={0}; si.cb= sizeof(si); PROCESS_INFORMATION pi; si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = TRUE; BOOL bRet = ::CreateProcess( NULL, szCommandLine, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi); if (bRet) { ::CloseHandle(pi.hThread); ::CloseHandle(pi.hProcess); printf("新的进程ID号:%d\n",pi.dwProcessId); printf("新进程的主线程ID号:%d\n",pi.dwThreadId); } system("pause"); return 0; }