进程介绍
1.任何进程都是进程创建的
explorer.exe
2.进程创建过程
- 映射exe文件
- 创建内核对象eprocess
- 映射系统DLL(ntdll.dll)
- 创建线程内核对象ETHREAD
-
系统启动线程
映射DLL(ntdll.LdrInitializeThunk)
线程开始执行
windows进程加载示意
每个进程都有一个句柄表
句柄是用来防止用户层直接操纵内核对象地址时出错从而导致操作系统崩溃而设置的内核对象的标识
全局句柄表:
操作系统用来保存所有的正在运行的进程的所有句柄的句柄表
pid和当前进程句柄:
pid是全局句柄表的一个编号
而当前进程句柄到别的进程就没有意义了
任务管理器里可以查看全局进程PID
线程的介绍
1.线程是附属在进程上的执行实体,是代码的执行流程
创建线程:
CreateThread(NULL,
0,
ThreadProc, //线程处理函数的名字
NULL,
0, //线程处理函数的传入值(LPVOID lpParam)
NULL)
2.线程的结束:
- 计数器为零
- 线程代码执行完毕
- 向线程传承参必须保证参数的生命周期长与线程的生命周期,否则会参数丢失
4.线程控制函数
Sleep()
SuspendThread()
ResumeThread()
WaitForSingleObject()
WaitForMultipleObjects()
GetExitCodeThread()
5.解决线程安全问题(多线程对全局变量的访问问题)
1.通过线程锁的实现来保证临界安全:
(临界区:一次只允许一个线程对变量进行访问)
1.创建全局变量
CRITICAL_SECTION cs
2.初始化全局变量
InitializeeCriticalSection(&cs)
3.实现临界区
EnterCriticalSection(&cs) //获取令牌
//使用临界资源
LeaveCriticalSection(&cs) //归还令牌
线程锁示意代码
#include<stdio.h>
#include<windows.h>
CRITICAL_SECTION cs;
int g_nCount = 10;
DWORD WINAPI ThreadProc1(LPVOID lpParam) {
EnterCriticalSection(&cs);
while (g_nCount > 0) {
printf(%d\n, g_nCount);
g_nCount--;
printf(**********%d\n, g_nCount);
}
LeaveCriticalSection(&cs);
return 0;
}
DWORD WINAPI ThreadProc2(LPVOID lpParam) {
EnterCriticalSection(&cs);
while (g_nCount > 0) {
printf(%d\n, g_nCount);
g_nCount--;
printf(**********%d\n, g_nCount);
}
LeaveCriticalSection(&cs);
return 0;
}
int main(int argc, char* argv[])
{
InitializeCriticalSection(&cs);
HANDLE hThread[2];
hThread[0] = CreateThread(NULL, 0, ThreadProc1, NULL, 0, NULL);
hThread[1] = CreateThread(NULL, 0, ThreadProc2, NULL, 0, NULL);
WaitForMultipleObjects(2, hThread, TRUE, INFINITE);
printf(线程执行完毕\n);
getchar();
CloseHandle(hThread[0]);
CloseHandle(hThread[1]);
return 0;
}
2.内核级的临界资源
互斥体:(内核级的令牌)
实现了跨进程中的不同进程中的不同线程都可以访问
互斥体和线程锁的区别:
- 互斥体可以通过多个进程访问
- 互斥体可以设值等待时间
- 线程意外终结时,互斥体可以避免无限等待
- 互斥体效率没有线程锁高
互斥体示意代码
#include<stdio.h>
#include<windows.h>
int main(int argc, char* argv[])
{
//创建一个互斥体
HANDLE g_hMutex = CreateMutex(NULL,FALSE,TEXT(MyMutex));
WaitForSingleObject(g_hMutex, INFINITE); //等待互斥体
for (int i = 0; i < 10; i++) {
Sleep(1000);
printf(Process B,Thread Y %d\n, i);
}
ReleaseMutex(g_hMutex); //释放互斥体
return 0;
}
若CreateMutex()重复创建,则返回创建了的互斥体的句柄,并且使用GetLastError()函数会得到 ERROR_ALREADY_EXIST 宏
事件:
(1)通知类型
g_hEvent = CreateEvent(NULL,
TRUE,
FALSE, //不设置通知状态
NULL
);
WaitForSingleObject(g_hEvent, INFINITE); //用于获得通知
SetEvent(g_hEvent); //用于挂起当前线程,唤醒设置线程
(2)线程同步
1.先保证线程互斥
2.再保证线程有序
Comments NOTHING