文章目录
1.创建进程API
BOOL CreateProcess(
LPCTSTR lpApplicationName, //指向可执行模块的名字,NULL
LPTSTR lpCommandLine, //传给新进程的命令行字符串,路径
LPSECURITY_ATTRIBUTES lpProcessAttributes, //指定进程的安全属性,NULL
LPSECURITY_ATTRIBUTES lpThreadAttributes, //指定线程的安全属性,NULL
BOOL bInheritHandles, //TRUE or FALSE
DWORD dwCreationFlags, //进程创建标识,0
LPVOID lpEnvironment, //为新进程指定环境字符串,NULL
LPCTSTR lpcurrentDirectory, //设定子进程的工作目录,NULL
LPSTARTUPINFO lpstartupInfo, //指向startupinfo的指针
LPPROCESS_INFORMATION lpProcessInformation //指向process_information指针
);
WCHAR lpPath[] = L"calc.exe";
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
BOOL bStatus = CreateProcess(NULL,lpPath,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi);
return 0;
2.创建线程API
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES 1pThreadAttributes, //线程安全属性,NULL
SIZE_T dwStacksize, //新线程的堆栈空间大小
LPTHREAD_START_ROUTINE lpStartAddress //新线程的函数地址
LPVOID lpParameter, //传递给新线程的数据
DWORD dwCreationFlags, //创建线程的方法
LPDWORD lpThreadId //用来接收新线程的ID,若为NULL,不返回线程ID
);
DWORD dwStackSize = 4 * 1024 * 1024;
DWORD dwProcessId = 0;
HANDLE hThread = CreateThread(NULL, dwStackSize, NewThread, NULL, 0, &dwProcessId);
3.使用ToolHelpAPI枚举进程
#include <iostream>
#include <fstream>
#include <windows.h>
#include <TlHelp32.h>
using namespace std;
#define MAX_BUF_SIZE 100
//枚举系统进程信息存入process.txt
BOOL EnumProcessInfo() {
//定义进程信息结构
PROCESSENTRY32 pe32 = { sizeof(pe32) };
//创建系统当前进程快照
HANDLE hProcessShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(hProcessShot == INVALID_HANDLE_VALUE)
return FALSE;
ofstream fout("process.txt");
//循环枚举进程信息
char szBuf[MAX_BUF_SIZE] = { 0 };
if (Process32First(hProcessShot, &pe32)){
do {
memset(szBuf, 0, sizeof(szBuf));
WideCharToMultiByte(CP_ACP,0,pe32.szExeFile,wcslen(pe32.szExeFile), szBuf, sizeof(szBuf), NULL, NULL);
fout << "Process:" << szBuf << endl;
fout << "ProcessID" << pe32.th32ProcessID << endl;
fout << "ThreadNum" << pe32.cntThreads << endl;
} while (Process32Next(hProcessShot, &pe32));
}
fout.close();
CloseHandle(hProcessShot);
return TRUE;
}
//枚举系统线程信息存入thread.txt
BOOL EnumThreadInfo() {
//定义线程信息结构
THREADENTRY32 te32 = { sizeof(te32) };
//创建系统当前线程快照
HANDLE hThreadShot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (hThreadShot == INVALID_HANDLE_VALUE)
return FALSE;
ofstream fout("thread.txt");
//循环枚举线程信息
if (Thread32First(hThreadShot, &te32)) {
do {
fout << "ThreadID:" << te32.th32ThreadID << endl;
fout << "OwnProcessID" << te32.th32OwnerProcessID << endl;
} while (Thread32Next(hThreadShot, &te32));
}
fout.close();
CloseHandle(hThreadShot);
return TRUE;
}
int main() {
EnumProcessInfo();
EnumThreadInfo();
return 0;
}
4.进程间通信
4.1.利用消息机制通信
发送端
HWND hWnd = ::FindWindow ( NULL, L"[第14章]进程间通信之消息通信机制——接收端" ) ;
if ( hWnd )
{
COPYDATASTRUCT CopyData = {0} ;
CopyData.dwData = GetCurrentProcessId() ;
CopyData.cbData = this->szData.GetLength() * 2 + 2 ;
CopyData.lpData = this->szData.GetBuffer ( CopyData.cbData ) ;
::SendMessage ( hWnd, WM_COPYDATA, NULL, (LPARAM)&CopyData ) ;
}
else
this->MessageBox ( L"没有接收端!" ) ;
接收端
BOOL CClientDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
{
CString szTempStr ;
szTempStr.Format ( L"[%d]%s%c%c", pCopyDataStruct->dwData, pCopyDataStruct->lpData, 0xd,0xa ) ;
this->szData += szTempStr ;
this->UpdateData ( FALSE ) ;
return CDialog::OnCopyData(pWnd, pCopyDataStruct);
}
适用于数据量较小的情况下,如果数据量达到1MB以上甚至更多,就不宜使用
4.2.利用共享内存
创建共享内存
HANDLE hMapFile ;
LPVOID lpData ;
void CIPC_ShareMemDlg::OnBnClickedCreate()
{
if ( this->lpData )
{
this->MessageBox ( L"共享内存已经存在!" ) ;
return ;
}
// 创建共享内存
this->hMapFile = CreateFileMapping ( INVALID_HANDLE_VALUE, \
NULL,PAGE_READWRITE | SEC_COMMIT,0,DEF_DATA_SIZE,L"ShareMemSample" ) ;
// 映射共享内存
if ( hMapFile )
this->lpData = MapViewOfFile ( hMapFile, FILE_MAP_READ|FILE_MAP_WRITE,0,0,0 ) ;
if ( this->hMapFile == NULL || this->lpData == NULL )
this->MessageBox ( L"创建共享内存映射文件失败!" ) ;
}
关闭共享内存
void CIPC_ShareMemDlg::OnBnClickedClose()
{
// 撤消映射的共享内存
if ( this->lpData )
UnmapViewOfFile ( this->lpData ) ;
// 关闭共享内存
if ( this->hMapFile )
CloseHandle ( this->hMapFile ) ;
}
写数据到共享内存
void CIPC_ShareMemDlg::OnBnClickedWrite()
{
if ( this->lpData == NULL )
{
this->MessageBox ( L"写入失败!" ) ;
return ;
}
UINT nLen = this->szData.GetLength()*2+2 ;
LPWSTR lpBuf = this->szData.GetBuffer( nLen ) ;
// 写入共享内存
memcpy ( this->lpData, (char*)lpBuf, nLen ) ;
// 检测是否需要通知到客户端
if ( ((CButton*)this->GetDlgItem(IDC_AUTO_NOTIFY))->GetCheck() == BST_CHECKED )
{
HWND hWnd = ::FindWindow ( NULL, L"[第14章]进程间通信之共享内存——读取端" ) ;
if ( hWnd )
{
// 使用自定义消息
::PostMessage ( hWnd, SHARE_MEM_NOTIFY, 0, 0 ) ;
}
}
}
读取数据
void CClientDlg::OnBnClickedRead()
{
HANDLE hMapFile = OpenFileMapping ( FILE_MAP_READ, FALSE, L"ShareMemSample");
if ( hMapFile == NULL )
{
DWORD dwErrorCode = GetLastError () ;
this->MessageBox ( L"打开共享内存映射文件失败!" ) ;
return ;
}
LPVOID lpBase = MapViewOfFile( hMapFile, FILE_MAP_READ,0,0,0 ) ;
if ( lpBase == NULL )
{
DWORD dwErrorCode = GetLastError () ;
this->MessageBox ( L"打开共享内存映射文件失败!" ) ;
return ;
}
this->szData.Format ( L"%s", (LPWSTR)lpBase ) ;
this->UpdateData ( false ) ;
UnmapViewOfFile ( lpBase ) ;
CloseHandle ( hMapFile ) ;
}
5.线程同步
5.1.原子操作
互锁系列函数InterlockedExchangeAdd
//函数定义
LONG InterlockedExchangeAdd(
LONG volatile* Target; //指向需要修改的整型数据
LONG Value; //需要增加的值
);
5.2.关键代码段
在使用临界对象之前首先需要使用InitiallizeCriticalSection进行初始化
void InitiallizeCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
获取访问权限才能使用临界对象执行关键代码段
//会阻塞线程
void EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
//不会阻塞线程
BOOL TryEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
离开代码段
void LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
当不使用临界对象,使用DeleteCriticalSection删除临界对象
void DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
实例如下:
#include <windows.h>
#include <iostream>
using namespace std;
#define DEF_DATA_SIZE 1024 // 定义数据大小
#define DEF_THREAD_NUM 30 // 定义线程数量
// 定义共享数据
typedef struct _SHARE_DATA {
LONG nCount ; // 操作次数
BYTE data[DEF_DATA_SIZE] ; // 共享数据主体
} SHARE_DATA ;
SHARE_DATA ShareData = {0};
// 定义临界区对象
CRITICAL_SECTION cs ;
// 工作线程
DWORD WINAPI WorkThread ( LPVOID lParam )
{
for ( int i = 0; i < 100; i++ )
{
// 进程临界区
EnterCriticalSection ( &cs ) ;
// 操作共享数据
ShareData.nCount ++ ;
for ( int i = 0; i < DEF_DATA_SIZE; i++ )
ShareData.data[i] = (BYTE)lParam ;
// 离开临界区
LeaveCriticalSection ( &cs ) ;
}
return 0 ;
}
int _tmain(int argc, _TCHAR* argv[])
{
// 初始化临界区对象
InitializeCriticalSection ( &cs ) ;
int i = 0 ;
HANDLE hThread[DEF_THREAD_NUM] = {0} ;
// 创建多个线程
for ( i = 0; i < DEF_THREAD_NUM; i++ )
{
hThread[i] = CreateThread ( NULL, 0, WorkThread, (LPVOID)i, 0, NULL ) ;
if ( hThread[i] == NULL )
{
cout << "创建线程失败" << endl ;
break ;
}
}
if ( i == DEF_THREAD_NUM )
{
// 等待所有线程结束
WaitForMultipleObjects ( DEF_THREAD_NUM, hThread, TRUE, INFINITE ) ;
cout << "count=" << ShareData.nCount << endl ;
}
// 关闭所有线程句柄
for ( i = 0; i < DEF_THREAD_NUM; i++ )
{
if ( hThread[i] )
CloseHandle ( hThread[i] ) ;
}
// 删除临界区对象
DeleteCriticalSection ( &cs ) ;
return 0;
}
5.3.内核对象与等待函数
一般来说,内核对象有两种状态:已通知状态和未通知状态,状态的切换是由系统为每种对象所建立的一套规则所决定的,当线程或进程结束时,系统就设置该内核对象为已通知状态,同时把等待在内核对象上的线程从阻塞状态转换到就绪状态。
等待函数能够使执行线程进入等待状态,直到其所等待的内核对象变为通知状态为止。
DWORD WaitForSingleObject(
HANDLE hHandle, //内核对象句柄
DWORD dwMilliseconds //等待超时时间,如果设置为INFINITE即为无超时时间
);
DWORD WaitForMultipleObjects(
DWORD nCount, //等待的内核对象数量
const HANDLE* lpHandles, //等待的内核对象句柄数组
BOOL bWaitAll, //标识是否等待所有内核对象都变为通知状态才返回
DWORD dwMilliseconds //等待超时时间
);
5.4.互斥内核对象
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes, //安全属性,NULL
BOOL bInitialOwner, //指定对象的初始状态,FALSE
LPCTSTR lpName //对象名称,NULL
);
HANDLE OpenMutex(
DWORD dwDesiredAccess, //访问方式
BOOL bInheritHandle, //是否可继承
LPCTSTR lpName //对象名称
);
实例
#include <windows.h>
#include <iostream>
using namespace std;
#define DEF_DATA_SIZE 1024 // 定义数据大小
#define DEF_THREAD_NUM 30 // 定义线程数量
// 定义共享数据
typedef struct _SHARE_DATA {
LONG nCount ; // 操作次数
BYTE data[DEF_DATA_SIZE] ; // 共享数据主体
} SHARE_DATA ;
SHARE_DATA ShareData = {0};
// 定义互斥对象
HANDLE hMutex = NULL;
// 工作线程
DWORD WINAPI WorkThread ( LPVOID lParam )
{
for ( int i = 0; i < 100; i++ )
{
// 获取互斥对象
WaitForSingleObject ( hMutex, INFINITE ) ;
// 操作共享数据
ShareData.nCount ++ ;
for ( int i = 0; i < DEF_DATA_SIZE; i++ )
ShareData.data[i] = (BYTE)lParam ;
// 释放互斥对象
ReleaseMutex ( hMutex ) ;
}
return 0 ;
}
int _tmain(int argc, _TCHAR* argv[])
{
// 创建互斥对象
hMutex = CreateMutex ( NULL, FALSE, NULL ) ;
if ( hMutex == NULL )
{
cout << "创建互斥对象失败!" << endl ;
return 0 ;
}
int i = 0 ;
HANDLE hThread[DEF_THREAD_NUM] = {0} ;
// 创建多个线程
for ( i = 0; i < DEF_THREAD_NUM; i++ )
{
hThread[i] = CreateThread ( NULL, 0, WorkThread, (LPVOID)i, 0, NULL ) ;
if ( hThread[i] == NULL )
{
cout << "创建线程失败" << endl ;
break ;
}
}
if (i == DEF_THREAD_NUM )
{
// 等待所有线程结束
WaitForMultipleObjects ( DEF_THREAD_NUM, hThread, TRUE, INFINITE ) ;
cout << "count=" << ShareData.nCount << endl ;
}
// 关闭所有线程句柄
for ( i = 0; i < DEF_THREAD_NUM; i++ )
{
if ( hThread[i] )
CloseHandle ( hThread[i] ) ;
}
// 删除互斥对象
CloseHandle ( hMutex ) ;
return 0;
}
版权声明:本文为qq_43647628原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。