线程/进程同步
1.互斥量
CreateMutex
Handle CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes,
BOOL bInitialOwner,
LPCTSTR lpName
);
•lpMutexAttributes,描述线程安全的结构体,默认传NULL.
• bInitialOwner,指示互斥对象的拥者,true调用线程获得互斥对象的所有权,false调用线程不获取互斥对象的所有权。
• lpName,互斥对象的名称,NULL表示匿名互斥对象。
OpenMutex
HANDLE OpenMutex(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
LPCTSTR lpName //名称
);
HANDLE WINAPI OpenMutexW(
_In_ DWORD dwDesiredAccess,
_In_ BOOL bInheritHandle,
_In_ LPCWSTR lpName
);
• dwDesiredAccess 表示访问权限,对互斥量一般传入MUTEX_ALL_ACCESS:请求对互斥体的完全访问;MUTEX_MODIFY_STATE:允许使用 ReleaseMutex 函数;SYNCHRONIZE:允许互斥体对象同步使用。
• bInheritHandle 表示互斥量句柄继承性,一般传入TRUE即可。
• lpName 表示名称。某一个进程中的线程创建互斥量后,其它进程中的线程就可以通过这个函数来找到这个互斥量。
ReleaseMutex
BOOL ReleaseMutex(HANDLE hMutex);
2.事件
CreateEvent
HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset,
BOOL bInitialState,
LPCTSTR lpName
);
• lpEventAttributes 表示安全控制,一般直接传入NUL
• bManualReset 确定事件是手动置位还是自动置位,传入TRUE表示手动置位,传入FALSE表示自动置位。如果为自动置位,则对该事件调用WaitForSingleObject()后会自动调用ResetEvent()使事件变成未触发状态。
• InitialState 表示事件的初始状态,传入TRUR表示已触发。
• pName 表示事件的名称,传入NULL表示匿名事件。
OpenEvent
HANDLE OpenEvent(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
LPCTSTR lpName //名称
);
• dwDesiredAccess 表示访问权限,对事件一般传入EVENT_ALL_ACCESS。详细解释可以查看MSDN文档。
• InheritHandle 表示事件句柄继承性,一般传入TRUE即可。
• pName 表示名称,不同进程中的各线程可以通过名称来确保它们访问同一个事件。
SetEvent
BOOL SetEvent(HANDLE hEvent);//设置事件的状态为信号状态,释放任意等待线程。
ResetEvent
BOOL ResetEvent(HANDLE hEvent);//设置事件对象为非信号状态
3.关键代码段
CRITICAL_SECTION cs;//定义一个全局锁,用于锁定一个资源
InitializeCriticalSection
VOID WINAPI InitializeCriticalSection(
LPCRITICAL_SECTION lpCriticalSection //临界资源对象指针。
);
EnterCriticalSection/LeaveCriticalSection
加锁————接下来的代码处理过程中不允许其他线程进行操作,除非遇到LeaveCriticalSection。
VOID WINAPI EnterCriticalSection(
_Inout_ LPCRITICAL_SECTION lpCriticalSection //临界资源对象指针。
);
解锁————EnterCriticalSection之间代码资源已经释放了,其他线程可以进行操作。
VOID WINAPI LeaveCriticalSection(
_Inout_ LPCRITICAL_SECTION lpCriticalSection //临界资源对象指针。
);
DeleteCriticalSection
// 此函数不返回值
VOID WINAPI DeleteCriticalSection(
_Inout_ LPCRITICAL_SECTION lpCriticalSection //临界资源对象指针。
);
4.信号量
CreateSemaphore
HANDLE CreateSemaphore(
LPSECURITY ATTRIBUTES lpSemaphoreAttributes, //安全属性
LONG lInitialCount, //设置信号量的初始计数
LONG lMaximumCount, //设置信号量的最大计数
LPCTSTR lpName //指定信号量对象的名称
);
• lpSemaphoreAttribute 指定安全属性,一般传入NULL
• lInitialCount 指定信号量对象的初始值。该值必须大于等于0,小于等于lMaximumCount。当其值大于0时,信号量被唤醒。当该函数释放了一个等待该信号量的线程时,lInitialCount值减1,当调用函数ReleaseSemaphore()时,按其指定的数量加一个值。
• lMaximumCount 指出该信号量的最大值,该值必须大于0。
• lpName 给出信号量的名字。
OpenSemaphore
HANDLE OpenSemaphore(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
LPCTSTR lpName
);
• wDesiredAccess 访问权限 ,一般传入SEMAPHORE_ALL_ACCESS ,要求对事件对象的完全访问;SEMAPHORE_MODIFY_STATE 允许使用ReleaseSemaphore函数;SYNCHRONIZE 允许同步使用信号机对象。
• bInheritHandle 表示信号量句柄继承性,一般传入TRUE即可
• lpName 表示名称,不同进程中的各线程可以通过名称来确保它们访问同一个信号量。
ReleaseSemaphore
BOOL ReleaseSemaphore(
HANDLE hSemaphore,
LONG lReleaseCount,
LPLONG lpPreviousCount
);
• hSemaphore 信号量句柄
• lReleaseCount 把lReleaseCount的值增加到当前资源计数上。表示增加个数,必须大于0且不超过最大资源数量。
• lpPreviousCount 返回当前资源计数的原始值,设为NULL表示不需要传出。
WaitForSingleObject/WaitForMultipleObjects
DWORD WaitForSingleObject(HANDLE hHandle,DWORD dwMilliseconds);//等待一个事件
DWORD WaitForMultipleObjects(//等待多个事件
DWORD nCount, // 等待句柄数
CONST HANDLE *lpHandles, //指向句柄数组
BOOL bWaitAll, //是否完全等待标志
DWORD dwMilliseconds //等待时间
);
• dwMilliseconds,超时时间间隔,0表示不阻塞,INFINITE表示一直阻塞。
• 返回值
WAIT_ABANDONED | 当hHandle为mutex时,如果拥有mutex的线程在结束时没有释放核心对象会引发此返回值。 |
---|---|
WAIT_OBJECT_0 | 等待超时 |
IT_TIMEOUT | 指定的对象出有有信号状态 |
IT_FAILED | 出现错误,可通过GetLastError得到错误代 |
进程
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
);
• lpApplicationName 设定所执行程序的名字(路径和文件名)
• lpCommandLine 传递命令行的参数
• lpProcessAttributes 一般传递NULL
• lpThreadAttributes 一般传递NULL
• bInheritHandles 是否新进程可以从调用进程继承
• dwCreationFlags 设置创建标记
• lpEnvironment 设置环境,一般传NULL
• lpCurrentDirectory 指示前的驱动器和目录(完成路径和文件名)
• lpStartupInfo 指定新进程的主窗口如何出现
• lpProcessInformation 接受新进程的标识信息
进程间通信
1.剪切板
OpenClipboard
BOOL OpenClipboard();//如果打开成功剪切板返回非零值,如果已经被打开返回零。
• 如果一个程序打开了剪切板,其他程序将不能使用剪切板,指导调用了CloseClipboard()。
• 只用调用了EmptyClipboard(),当前窗口才拥有剪切板。
EmptyClipboard
BOOL EmptyClipboard(VOID);//清空剪切板,并释放剪切板中数据的句柄,将剪切板的所有权分配给打开剪切板 的窗口。
SetClipboardData
HANDLE SetClipboardData(
UINT uFormat, //指定剪切板格式(CF_TEXT 文本格式)
HANDLE hMem //数据句柄
);
• 延迟提交技术:先将hMem设置为NULL,直到程序需要数据时才真正提交数据。但是需要先处理WM_RENDERFORMAT和WM_RENDERALLFORMATS消息。
GetClipboardData
HANDLE GetClipboardData(UINT uFormat);
IsClipboardformatAvailable(UINT format);
GlobalAlloc
HGLOBAL GlobalAlloc(
UINT uFlags,//指定如何分配内存
SIZE_T dwBytes //
);
GlobalLock/GlobalUnlock/GlobalRelock
LPVOID GlobalLock(HGLOBAL hMem);//对全局内存对象加锁
CloseClipboard
CloseClipboard();
2.匿名管道
一个进程创建其他进程连接,并可以进行双向通信。
BOOL CreatePipe(
PHANDLE hReadPipe,
PHANDLE hWritePipe,
LPSECURITY_ATTRIBUTES lpPipeAttributes,
DWORD nSize
);
• hReadPipe 管道读取句柄
• hWritePipe 管道写入句柄
• lpPipeAttributes 检测管道是否可以被继承
• nSize 管道大小,如果传入0,系统使用缺省值。
3.命名管道
可以实现网络间两个进程的通信
CreateNamedPipe
HANDLE CreateNamedPipe(
LPCTSTR lpName,
DWORD dwOpenMode,
DWORD dwPipeMode,
DWORD nMaxInstances,
DWORD nOutBufferSize,
DWORD nInBufferSize,
DWORD nDefaultTimeOut,
LPSECURITY_ATTRIBUTES lpSecurityAttributes
);
• lpName 管道名称(固定形式: \.\pipe\pipeName,pipeName部分可改变)
• dwOpenMode 管道访问方式(PIPE_ACCESS_DUPLEX 可读可写,PIPE_ACCESS_INBOUND 只读,PIPE_ACCESS_OUTBOUND 只写,FILE_FLAG_OVERLAPPED重叠模式)
• dwPipeMode 读取和等待的方式(PIPE_TYPE_BYTE,PIPE_TYPE_MESSAGE,默认为0)
• nMaxInstances 同时可以连接的客户端数目
• nOutBufferSize 输出缓冲区大小
• nInBufferSize 输入缓冲区大小
• nDefaultTimeOut 缺省超时值
• lpSecurityAttributes 安全属性
ConnectNamedPipe
BOOL ConnectNamedPipe { //服务器端等待客户端的连接请求
HANDLE hNamedPipe, //命名管道的句柄
LPOVELAPPED lpOverlapped //如果dwOpenMode的属性包含FILE_FLAG_OVERLAPPED,则这个结构体必须包含手动释放的event事件。
}
WaitNamedPipe
BOOL WaitNamedPipe { //客户端等待服务端的管道连接
LPCTSTR lpNamedPipeName, //管道名称
DWORD nTimeout //超时值(NMPWAIT_WAIT_FOREVER)
}
4.油槽
油槽是基于广播通信体系设计出来的,采用无连接不可靠的数据传输,是一种单向通信机制。要将消息长度限制在424字节一下。一个进程创建并拥有一个邮槽,其他进程都可以打开这个邮槽并向其发送消息。
CreateMailslot
HANDLE CreateMailslot(
LPCTSTR lpName,
DWORD nMaxMessageSize,
DWORD lReadTimeout,
LPSECURITY_ATTRIBUTES lpSecurityAttributes
);
• lpName 油槽名字(\.mailsort\name 与有名管道类似)
• nMaxMessageSize 被写入消息最大尺寸。一般指定为0,表示可以是任意大小(最好不超过424字节)。
• lReadTimeout 超时间隔
• lpSecurityAttributes 一般传NULL
CreateFile 打开邮槽
HANDLE CreateFile(
LPCTSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile
);
• lpFileName 文件名
• dwDesiredAccess 访问方式
• dwShareMode 共享方式
• lpSecurityAttributes 一般传NULL
• dwCreationDisposition 打开方式
• dwFlagsAndAttributes 文件属性
• hTemplateFile 一般传NULL
5.共享内存(映射文件)
CreateFileMapping
HANDLE WINAPI CreateFileMapping(
_In_ HANDLE hFile,
_In_opt_ LPSECURITY_ATTRIBUTES lpAttributes,
_In_ DWORD flProtect,
_In_ DWORD dwMaximumSizeHigh,
_In_ DWORD dwMaximumSizeLow,
_In_opt_ LPCTSTR lpName
);
• hFile 用于创建文件映射对象的文件的句柄。一般情况我们将这个参数设置为INVALID_HANDLE_VALUE,如果hFile设为INVALID_HANDLE_VALUE,调用进程还必须在dwMaximumSizeHigh和 dwMaximumSizeLow参数中指定文件映射对象的大小。
• lpAttributes 保护设置或者称为安全设置,一般设置为NULL,这样就是windows的默认安全设置
• flProtect 访问权限设置,通常有PAGE_READONLY、PAGE_READWRITE和PAGE_WRITECOPY,释义分别为只读,可读写,写时复制访问(留下备份)
• dwMaximumSizeHigh和dwMaximumSizeLow 高低位文件大小,当flProtect 设置为只读时,这样我们并不改变其大小,所以可以将这两个参数设置为0。否则我们将dwMaximumSizeHigh设置为0,dwMaximumSizeLow设置为我们想开辟的内存字节数。
• lpName 共享文件内存的名称
MapViewOfFile
LPVOID WINAPI MapViewOfFile(
_In_ HANDLE hFileMappingObject,
_In_ DWORD dwDesiredAccess,
_In_ DWORD dwFileOffsetHigh,
_In_ DWORD dwFileOffsetLow,
_In_ SIZE_T dwNumberOfBytesToMap
);
• hFileMappingObject 文件映射对象的句柄。接收CreateFileMapping和 OpenFileMapping函数返回该句柄
• dwDesiredAccess 访问文件映射对象的类型(权限)。要与在CreateFileMapping()时设置的访问权限相匹配。FILE_MAP_ALL_ACCESS等价于CreateFileMapping的FILE_MAP_WRITE|FILE_MAP_READ. 文件映射对象被创建时必须指定PAGE_READWRITE选项.
FILE_MAP_COPY可以读取和写入文件.写入操作会导致系统为该页面创建一份副本.在调用CreateFileMapping时必须传入PAGE_WRITECOPY保护属性
• dwFileOffsetHigh和dwFileOffsetLow 文件映射起始偏移的高32位和低32位,通常情况都设置为0
• dwNumberOfBytesToMap 指定需要映射的文件的字节数量,当dwNumberOfBytesToMap为0,则映射的是整个文件
• 返回值:当文件成功映射时则返回的值是映射到进程地址空间的首地址
HANDLE WINAPI OpenFileMapping(
_In_ DWORD dwDesiredAccess, //访问文件映射对象的类型(权限)
_In_ BOOL bInheritHandle, //设为TRUE,CreateProcess创建的进程可以继承该句柄,否则不能被继承
_In_ LPCTSTR lpName //要打开的文件映射对象的名称
);
HOOK
用于过滤消息。
SetWindowsHookEx 安装钩子
HHOOK SetWindowsHookEx(
int idHook,
HOOKPROC lpfn,
HINSTANCE hMod,
DWORD dwThreadId
);
• idHook 指定要安装的钩子类型
• lpfn 设定hook入口
• hMod 动态链接库句柄,如果与当前进程相关,则该参数设置为NULL。
• dwThreadId 指定和钩子过程相关的过程标识符,设为0则表示和运行在同一桌面上的线程都相关。
钩子过程固定写法
LRESULT CALLBACK ShellProc(
int nCode,
WPARAM wParam,
LPARAM lParam
);
CallNextHookEx 调用下一个钩子
CallNextHookEx(
HHOOK hhk
int nCode, //hhk 当前hook句柄
WPARAM wParam,
LPARAM lParam
);
UnhookWindowsHookEx
BOOL UnhookWindowsHookEx(HHOOK hhk);