创建进程
WIN32 API提供了CreateProcess函数,用来创建一个新的进程和它的主线程。
//CreateProcess函数原型
BOOL WINAPI CreateProcess(
_In_opt_ LPCTSTR lpApplicationName,
_Inout_opt_ LPTSTR lpCommandLine,
_In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_ BOOL bInheritHandles,
_In_ DWORD dwCreationFlags,
_In_opt_ LPVOID lpEnvironment,
_In_opt_ LPCTSTR lpCurrentDirectory,//工作目录
_In_ LPSTARTUPINFO lpStartupInfo,
_Out_ LPPROCESS_INFORMATION lpProcessInformation
);
其中STARTUPINFO结构体信息,可以通过GetStartupInfo函数来填充,这样,父进程的STARTUPINFO结构体信息就可以用到子进程的创建上。
typedef struct _STARTUPINFO {
DWORD cb;
LPTSTR lpReserved;
LPTSTR lpDesktop;
LPTSTR lpTitle;
DWORD dwX;
DWORD dwY;
DWORD dwXSize;
DWORD dwYSize;
DWORD dwXCountChars;
DWORD dwYCountChars;
DWORD dwFillAttribute;
DWORD dwFlags;
WORD wShowWindow;
WORD cbReserved2;
LPBYTE lpReserved2;
HANDLE hStdInput;
HANDLE hStdOutput;
HANDLE hStdError;
} STARTUPINFO, *LPSTARTUPINFO;
VOID WINAPI GetStartupInfo(
_Out_ LPSTARTUPINFO lpStartupInfo
);
dwCreationFlags参数用于设置进程的创建模式和优先级。
其中进程的创建标志详见:
Process Creation Flags
https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863(v=vs.85).aspx
优先级标志详见:
GetPriorityClass function
https://msdn.microsoft.com/en-us/library/windows/desktop/ms683211(v=vs.85).aspx
优先级由高到低为:IDLE_PRIORITY_CLASS,BELOW_NORMAL_PRIORITY_CLASS,NORMAL_PRIORITY_CLASS,ABOVE_NORMAL_PRIORITY_CLASS,HIGH_PRIORITY_CLASS,REALTIME_PRIORITY_CLASS。
创建线程
WIN32 API提供了CreateThread函数,用来创建一个新线程。
//CreateThread函数原型
HANDLE WINAPI CreateThread(
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_ SIZE_T dwStackSize,
_In_ LPTHREAD_START_ROUTINE lpStartAddress,
_In_opt_ LPVOID lpParameter,
_In_ DWORD dwCreationFlags,
_Out_opt_ LPDWORD lpThreadId
);
其中lpThreadAttributes指向一个SECURITY_ATTRIBUTES,该结构体声明如下。其中nLength设置为sizeof(SECURITY_ATTRIBUTES),lpSecurityDescriptor指向一个SECURITY_DESCRIPTOR结构体,设置为NULL则子线程会沿用父线程的ACL,bInheritHandle指定创建的线程的句柄可否被继承。
在调用CreateThread时该函数可以置NULL,意味沿用父进程的ACL并且句柄不可被继承。
typedef struct _SECURITY_ATTRIBUTES {
DWORD nLength;
LPVOID lpSecurityDescriptor;
BOOL bInheritHandle;
}SECURITY_ATTRIBUTES,*PSECURITY_ATTRIBUTES,*LPSECURITY_ATTRIBUTES;
dwStackSize参数设置线程的栈大小,设置为0会使用一个系统默认的栈大小。
lpStartAddress参数指向线程的运行函数地址。该线程运行函数应和以下函数原型相符。
DWORD WINAPI ThreadProc(
_In_ LPVOID lpParameter
);
lpParameter参数就是希望传递给线程运行函数的参数,如果希望传递多个参数,可以以结构体的形式,将结构体指针作为void*传递。
dwCreationFlags参数可以设置线程创建后是立即运行还是挂起。0表示立即运行,CREATE_SUSPENDED表示创建后挂起线程。
lpThreadId参数是个输出参数,用于接受线程id。
返回值是一个句柄,如果线程创建成功,返回线程句柄,如果失败返回NULL,调用GetLastError获得错误信息。
上面讲到的是WIN32提供的API函数,而MFC也提供了创建线程的函数,虽然本质上也是通过调用WIN32 API函数CreateThread实现的,但是为用户封装了许多操作,提供了现成的功能,例如消息循环等。
MFC提供的线程创建
//AfxBeginThread函数原型
CWinThread* AfxBeginThread(
AFX_THREADPROC pfnThreadProc,
LPVOID pParam,
int nPriority = THREAD_PRIORITY_NORMAL,
UINT nStackSize = 0,
DWORD dwCreateFlags = 0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL
);
CWinThread* AfxBeginThread(
CRuntimeClass* pThreadClass,
int nPriority = THREAD_PRIORITY_NORMAL,
UINT nStackSize = 0,
DWORD dwCreateFlags = 0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL
);
第一个AfxBeginThread用于创建工作线程,参数根据形参英文简单明了,不说太多。在MFC中,创建工作线程会构造一个CWinThread对象(与UI线程使用的CWinThread构造函数不同),并调用CWinThread::CreateThread创建线程,之后直接进入线程函数而不进入run()消息循环。
第二个AfxBeginThread用于创建UI线程,创建方法大致如下:
1.从CWinThread派生一个自己的CUIThread类。
2.在CUIThread类中重载InitInstance函数,创建自己界面之类云云,此处要注意设置CWinThread::m_hMainWnd成员,不然线程不会随着窗口关闭而结束。(工作线程的CWinThread::m_hMainWnd成员会直接继承父线程的)
3.调用AfxBeginThread(RUNTIME_CLASS(CUIThread))启动线程。