win3212进程和线程Word格式文档下载.docx
《win3212进程和线程Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《win3212进程和线程Word格式文档下载.docx(16页珍藏版)》请在冰点文库上搜索。
![win3212进程和线程Word格式文档下载.docx](https://file1.bingdoc.com/fileroot1/2023-4/30/7c0f3cbd-fd1c-4e58-abdf-fe63c57f5d27/7c0f3cbd-fd1c-4e58-abdf-fe63c57f5d271.gif)
CreateProcess-目前最多使用
BOOLCreateProcess(
LPCTSTRlpApplicationName,//应用程序名称
LPTSTRlpCommandLine,//命令行参数
LPSECURITY_ATTRIBUTESlpProcessAttributes,//进程安全属性SD
LPSECURITY_ATTRIBUTESlpThreadAttributes,
//线程安全属性SD
BOOLbInheritHandles,//进程的句柄继承
DWORDdwCreationFlags,//创建方式
LPVOIDlpEnvironment,//环境信息
LPCTSTRlpCurrentDirectory,//当前目录
LPSTARTUPINFOlpStartupInfo,//起始信息
LPPROCESS_INFORMATIONlpProcessInformation
//返回进程和线程的句柄ID
);
2结束进程
VOIDExitProcess((本进程自杀)
UINTuExitCode//exitcodeforallthreads
BOOLTerminateProcess((杀人)
HANDLEhProcess,//handletotheprocess
UINTuExitCode//exitcodefortheprocess
3打开进程
HANDLEOpenProcess(
DWORDdwDesiredAccess,//访问权限
BOOLbInheritHandle,//继承标识(是否可以被当前进程的子进程使用)
DWORDdwProcessId//进程ID
返回进程句柄
4关闭进程句柄
CloseHandle
5进程间的等候
等候可等候的句柄的信号
可等候的句柄:
必须有两种状态1.有信号状态,2.无信号状态
DWORDWaitForSingleObject(
HANDLEhHandle,//句柄
DWORDdwMilliseconds//等候时间(毫秒为单位)
一般为INFINEITE(代表等候时间无限大)
阻塞函数,等候句柄的信号,只在句柄有信号或超出等候时间,才会结束等候。
Windows线程
Windows线程是可以执行的代码的实例。
系统是以线程为单位调度程序。
一个程序当中可以有多个线程,实现多任务的处理。
Windows线程的特点:
1)线程都具有1个ID
2)线程具有自己的安全属性
3)每个线程都具有自己的内存栈
4)每个线程都具有自己的寄存器信息
进程多任务和线程多任务:
进程多任务是每个进程都使用私有地址空间,
线程多任务是进程内的多个线程使用同一个地址空间。
线程的调度:
将CPU的执行时间划分成时间片,依次根据时间片执行不同的线程。
在CPU眼中,不认进程关系,按时间片安排执行线程
线程轮询:
线程A->
线程B->
线程A......
•线程的使用
1定义线程处理函数
DWORDWINAPIThreadProc(
LPVOIDlpParameter//创建线程时,传递给线程的参数
2创建线程
HANDLECreateThread((仅仅是运行定义起来,有没有运行,要看是否被调用)
LPSECURITY_ATTRIBUTESlpThreadAttributes,//安全属性
SIZE_TdwStackSize,(0默认大小1M)//线程栈的大小
LPTHREAD_START_ROUTINElpStartAddress,//线程处理函数的函数地址(用来执行该线程要设定的任务)
LPVOIDlpParameter,//传递给线程处理函数的参数
DWORDdwCreationFlags,//线程的创建方式,
LPDWORDlpThreadId(线程ID由系统分配)//创建成功,返回线程的ID
创建成功,返回线程句柄
dwCreationFlags:
0-创建之后线程立刻执行
CREATE_SUSPENDED-创建之后线程处于挂起状态。
(不执行,挂起休眠)
3结束线程
结束指定线程
BOOLTerminateThread(
HANDLEhThread,//handletothread
DWORDdwExitCode//exitcode
结束函数所在的线程
VOIDExitThread(
DWORDdwExitCode//exitcodeforthisthread
4关闭线程句柄
CloseHandle
5线程的挂起和执行
挂起
DWORDSuspendThread(
HANDLEhThread//handletothread
执行
DWORDResumeThread(
6线程的信息
GetCurrentThreadId-获取当前线程的ID
GetCurrentThread-获取当前线程的句柄
根据线程ID,获取其句柄
HANDLEOpenThread(
DWORDdwDesiredAccess,//accessright
BOOLbInheritHandle,//handleinheritanceoption
DWORDdwThreadId//threadidentifier
第三个参数是线程的ID则返回线程的句柄
•多线程的问题
线程A。
。
当线程A执行printf输出时,如果线程A的执行时间结束,系统会将线程A的相关信息(栈、寄存器)压栈保护,同时将线程B相关信息恢复,然后执行线程B,线程B继续输出字符。
由于线程A正输出字符,线程B会继续输出,画面字符会产生混乱。
_declspec(thread)CHARg_szText[256]={0};
//全局变量时候,随时多线程,但一次只能有一个线程使用该全局变量所以加上前缀解决该问题
//前缀说明每个线程使用的都是该全局比那两的副本,全局变量本身不做变化
线程同步技术day14/WinTls
线程同步技术
原子锁
临界区(段)
事件
互斥
信号量
可等候计时器(略)
实现加锁(类似于在UC中的)机制的有临界区(段)(多个线程共同使用的资源)互斥
•等候函数
WaitForSingleObject-等候单个
WaitForMultipleObjects-等候多个
DWORDWaitForMultipleObjects(
DWORDnCount,//句柄数量
CONSTHANDLE*lpHandles,//句柄BUFF的地址
BOOLbWaitAll,//等候方式
DWORDdwMilliseconds//等候时间
返回值
WAIT_TIMEOUT时间到
bWaitAll-等候方式
TRUE-表示所有句柄都有信号,才结束等候
FASLE-表示句柄中只要有1个有信号,就结束等候。
1.原子锁(时间消耗)
相关问题day14/WinInter
多个线程对同一个数据进行原子操作,会产生结果
丢失。
比如执行++运算时,
当线程A执行g_nValue1++时,如果线程切换时间
正好是在线程A将值保存到g_nValue1之前,
线程B继续执行g_nValue1++,那么当线程A再次被切换回来之后,会将原来线程A保存的值保存到g_nValue1上,线程B进行的加法操作被覆盖。
---------------------------------例WinInter解析-------------------------------
两个线程自加同一个变量
自加操作时候的汇编代码
00401063movecx,dwordptr[g_nValue(00427c48)]
00401069addecx,1
0040106Cmovdwordptr[g_nValue(00427c48)],ecx
00401072jmpTestProc1+21h(00401051)
ecx=g_nValue;
ecx=ecx+1;
g_nValue=ecx;
线程A
1..----------------------------------时间片到将ecx压站保护ecx=1;
3..----------------------------------g_nValue=1;
线程B
2..------------------------------时间片到g_nValue等于1
执行顺序1.3.2
原子锁就能够解决这个问题
---------------------------------------------------------------------------------
•原子锁的使用
原子锁-对单条指令的操作。
每一个运算符都有一个原子锁函数
API
InterlockedIncrement内存数据加函数(自加原子锁)
InterlockedDecrement内存数据减函数(自减原子锁)
InterlockedCompareExchangea>
=3时a=3
InterlockedExchange赋值
...
原子锁的实现:
直接对数据所在的内存操作,并且在任何一个瞬间只能有一个线程访问。
2.临界区
相关问题day//WinThread
printf输出混乱,多线程情况下同时使用一段代码。
临界区可以锁定一段代码,防止多个线程同时使用该段代码
使用WinCritical(完全可以替代原子锁的使用)
1初始化一个临界区(初始化临界区变量)
VOIDInitializeCriticalSection(
LPCRITICAL_SECTIONlpCriticalSection
//临界区变量
2进入临界区
添加到被锁定的代码之前
VOIDEnterCriticalSection(
LPCRITICAL_SECTIONlpCriticalSection//criticalsection结构体指针
3离开临界区
添加到被锁定的代码之后
VOIDLeaveCriticalSection(
LPCRITICAL_SECTIONlpCriticalSection//criticalsection
4删除临近区
VOIDDeleteCriticalSection(
第一、四步都用在主线程中
第二、三步都用在子线程(需要上锁的代码段)中
•原子锁和临界区
原子锁-单条指令。
临界区-单条或多行代码。
原子锁锁定单独指令临界区是范围锁定()
3.事件(多个子进程之间通知问题)
相关问题WinEvent
程序之间的通知的问题。
事件的使用
1创建事件
HANDLECreateEvent(
LPSECURITY_ATTRIBUTESlpEventAttributes,//安全属性
BOOLbManualReset,
//事件重置方式,TRUE手动,FALSE自动
BOOLbInitialState,//事件初始状态,TRUE有信号
LPCTSTRlpName//事件命名
创建成功返回事件句柄
事件重置方式或复位:
从有信号变成无信号
2等候事件
WaitForSingleObject/
WaitForMultipleObjects
3触发事件
将事件设置成有信号状态
BOOLSetEvent(
HANDLEhEvent//handletoevent事件句柄
将事件设置成无信号状态
BOOLResetEvent(复位事件
HANDLEhEvent//handletoevent
4关闭事件CloseHandle
小心事件的死锁。
4.互斥Mutex
相关的问题WinMutex
多线程下代码或资源的共享使用。
互斥的使用
1创建互斥
HANDLECreateMutex(
LPSECURITY_ATTRIBUTESlpMutexAttributes,
//安全属性
BOOLbInitialOwner,//初始的拥有者
LPCTSTRlpName//命名
创建成功返回互斥句柄
bInitialOwner-初始的拥有者
互斥的游离状态表示有信号,线程得到后就处于无信号状态
TRUE-调用CreateMutex的线程拥有互斥
FALSE-创建的时没有线程拥有互斥
2等候互斥
WaitFor....
互斥的等候遵循谁先等候谁先获取。
互斥游离时候没有堵塞,某个线程拿到互斥后,互斥变为无信号状态,进入堵塞阶段,当拥有该互斥的线程释放了互斥后,应用进程才继续进行,哪个线程先进入堵塞(类似排队),哪个线程就得到新的游离互斥,重新进入堵塞状态
3释放互斥
BOOLReleaseMutex(
HANDLEhMutex//handletomutex
4关闭互斥句柄
互斥和临界区的区别
临界区-用户态,执行效率高,只能在同一个进程中使用。
互斥-内核态,执行效率低,可以通过命名的方式跨进程使用。
5.信号量
相关的问题
类似于事件,解决通知的相关问题。
但是可以提供一个计数器,可以设置次数。
信号量的使用
1创建信号量
HANDLECreateSemaphore(
LPSECURITY_ATTRIBUTESlpSemaphoreAttributes,
LONGlInitialCount,//初始化信号量数量(3)
LONGlMaximumCount,//信号量的最大值(10)
LPCTSTRlpName//命名
创建成功返回信号量句柄
2等候信号量
WaitFor...(第一次碰到的时候不会阻塞,计数3变成2,每遇到一个信号计数就会递减,都不会阻塞,当计数为0之后,就都会阻塞)
等候每通过一次,信号量的信号减1,直到为0阻塞
3释放信号量
BOOLReleaseSemaphore((重新给信号量一个计数值)
HANDLEhSemaphore,//信号量句柄(给哪个信号一个新的值)
LONGlReleaseCount,//释放数量(重新赋的值)
LPLONGlpPreviousCount
//释放前原来信号量的数量,可以为NULL
4关闭句柄
6.可等候计时器(略)
.
相关问题
按指定的间隔时间通知程序
精度高(纳秒级,以100纳秒为单位,只适用于第一次启动时间,间隔时间仍然是以毫秒为单位)
准度好(不走队列,不需要getmessage抓取消息)
可等候计时器的使用
1.创建可等候计时器
HANDLECreateWaitableTimer(
LPSECURITY_ATTRIBUTESlpTimerAttributes,//SD安全属性没默认为null
BOOLbManualReset,//resettype复位方式,TRUE-手动,FALSE–自动
LPCTSTRlpTimerName//objectname命名。
可以为null
、、函数执行成功,返回可等候定时器句柄
2.设置可等候计时器(启动时间,间隔时间)
Setwaitabletimer
BOOLSetWaitableTimer(
HANDLEhTimer,//handletotimer
定时器句柄
constLARGE_INTEGER*pDueTime,//timerduetime
(代表六十四位结构体)第一次启动时间
LONGlPeriod,//timerinterval
间隔时间(毫秒)
PTIMERAPCROUTINEpfnCompletionRoutine,//completionroutine
APC回调函数(自己定义,定时时间到,则调用)
LPVOIDlpArgToCompletionRoutine,//completionroutineparameter
APC回调函数的参数
BOOLfResume//resumestate待机处理标识(TRUE、false)
pDuTime-
正数-绝对时间,具体系统时间(年月日分秒)
负数-相对时间,和单签时间的时间差
lPeriod–
单位为毫秒,如果为0,可等候定时器只执行一次。
fResume–
TRUE-时间到了,唤醒机器,继续运行
False-取消通知,不唤醒,继续待机
3.等候
WaitFor…
4.关闭可等候定时器句柄