Windows线程开发
Windows线程开发
1.线程基础
Windows线程是可以执行的代码实例。系统十一线程为单位调度程序。一个程序当中可以有多个线程,实现多个任务的处理。
Windows线程的特点:
- 线程都具有1个ID
- 每个线程都具有自己的内存栈
- 同一进程中的线程使用同一个地址空间
线程的调度
操作系统将CPU的执行时间划分成时间片,依次根据时间片执行不同的线程。线程轮询:线程A->线程B->线程A......
2.创建线程
创建线程
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes, //安全属性
SIZE_T dwStackSize, //线程栈的大小
LPTHREAD_START_ROUTINE lpStartAddress, //线程处理函数的函数地址
LPVOID lpParameter, //传递给线程处理函数的参数
DWORD dwCreationFlags, //线程创建方式
LPDWORD lpThreadId //创建成功,返回线程的ID
);创建成功,返回线程句柄
定义线程处理函数
DWORD WINAPI ThreadProc(
LPVOID lpParameter //创建线程时,传递给线程的参数
);
例子:
#include <Windows.h>
#include <stdio.h>
DWORD CALLBACK ThreadProc(LPVOID param){
char* pszText = (char*) param;
while(1){
printf("%s\n",pszText);
Sleep(1000);
}
return 0;
}
int main(){
DWORD pid = 0;
char* pszText="******";
HANDLE hThread = CreateThread(NULL,0,ThreadProc,pszText,0,&pid);
getchar();
return 0;
}
3.线程挂起/销毁
挂起
DWORD SuspendThread(
HANDLE hThread //handle to thread
);
唤醒
DWORD ResumeThread(
HANDLE hThread //handle to thread
);
例子:
#include <Windows.h>
#include <stdio.h>
DWORD CALLBACK ThreadProc(LPVOID param){
char* pszText = (char*) param;
while(1){
printf("%s\n",pszText);
Sleep(1000);
}
return 0;
}
DWORD CALLBACK ThreadProc2(LPVOID param){
char* pszText = (char*) param;
while(1){
printf("%s\n",pszText);
Sleep(1000);
}
return 0;
}
int main(){
DWORD pid = 0;
char* pszText="<<<<<<";
HANDLE hThread = CreateThread(NULL,0,ThreadProc,pszText,0,&pid); //创建的线程立即执行
char* pszText2 = ">>>>>>";
HANDLE hThread2 = CreateThread(NULL,0,ThreadProc2,pszText2,CREATE_SUSPENDED,&pid); //创建的线程挂起
getchar();
SuspendThread(hThread);
ResumeThread(hThread2);
getchar();
return 0;
}
4.线程相关操作
结束指定线程
BOOL TerminateThread(
HANDLE hTread, //handle to thread
DWORD dwExitCode //exit code
);
结束函数所在的线程
VOID ExitThread(
DWORD dwExitCode //exit code for this thread
);
获取当前线的ID
GetCurrentThreadId();
获取当前线程的句柄
GetCurrentThread();
等候单个句柄有信号
VOID WaitForSingleObject(
HANDLE handle, //句柄BUFF的地址
DWORD dwMillseconds //等候时间INFINITE(无限大)
);
同时等候多个句柄有信号
DWORD WaitForMultipleObjects(
DWORD nCount, //句柄数量
CONST HANDLE *lpHandles, //句柄BUFF的地址
BOOL bWaitAll, //等候方式
DWORD dwMillisenconds //等候时间INFINITE
);
bWaitAll - 等候方式:
TRUE - 表示所有句柄都有信号,才结束等候
FALSE - 表示句柄中只要有1个有信号,就结束等候
5.线程同步
5.1 原子锁
相关问题
多个线程对同一个数据进行原子操作,会产生结果丢失。比如执行++运算时。
错误代码分析
当线程A执行g_value++时,如果线程切换时间正好是线程A将值保存到g_value之前线程B继续执行g_value++,那么当线程A再次切换回来之后,会将原来线程A保存的值保存到g_value上,线程B进行的加法操作被覆盖。
使用原子锁函数
InterlockedIncrement
InterlockedDecrement
InterlockedCompareExchange
InterlockedExchange
...
原子锁的实现:直接对数据所在的内存操作,并且 在任何一个瞬间只能有一个线程访问。
5.2 互斥
相关的问题
多线程下代码或资源的共享使用。
互斥的使用
创建互斥
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes, //安全属性
BOOL bInitialOwner, //初始的拥有者 TRUE/FALSE
LPCTSTR lpName //命名
); 创建成功返回互斥句柄
等候互斥
WaitFor... 互斥的等候遵循谁先等候谁先获取。
释放互斥
BOOL ReleaseMutex(
HANDLE hMutex //handle to mutex
);
关闭互斥句柄
CloseHandle(
HANDLE hMutex
);
例子:
#include <Windows.h>
#include <stdio.h>
HANDLE g_hMutex = 0; //获得互斥句柄
DWORD CALLBACK ThreadProc(LPVOID param){
char* pszText = (char*) param;
while(1){
/*printf("%s\n",pszText);
Sleep(1000);*/
WaitForSingleObject(g_hMutex,INFINITE);
for(int i = 0; i < strlen(pszText); i++){
printf("%c",pszText[i]);
Sleep(125);
}
printf("\n");
ReleaseMutex(g_hMutex);
}
return 0;
}
DWORD CALLBACK ThreadProc2(LPVOID param){
char* pszText = (char*) param;
while(1){
/*printf("%s\n",pszText);
Sleep(1000);*/
WaitForSingleObject(g_hMutex,INFINITE);
for(int i = 0; i < strlen(pszText); i++){
printf("%c",pszText[i]);
Sleep(125);
}
printf("\n");
ReleaseMutex(g_hMutex);
}
return 0;
}
int main(){
g_hMutex = CreateMutex(NULL,FALSE,NULL);
DWORD pid = 0;
char* pszText="<<<<<<";
HANDLE hThread = CreateThread(NULL,0,ThreadProc,pszText,0,&pid); //创建的线程立即执行
char* pszText2 = ">>>>>>";
HANDLE hThread2 = CreateThread(NULL,0,ThreadProc2,pszText2,0,&pid);
getchar();
CloseHandle(g_hMutex);
return 0;
}
5.3 事件
相关问题
程序之间的通知的问题。
事件的使用
创建事件
HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes, //安全属性
BOOL bManualReset,
//事件重置(复位)方式,TRUE手动,FALSE自动
BOOL bInitialState, //事件初始状态,TRUE有信号
LPCTSTR lpName //事件命名
);创建成功返回事件句柄
等候事件
WaitForSingleObject
/WaiteForMultipleObjects
触发事件(将事件设置成有信号状态)
BOOL SetEvent(
HANDLE hEvent //handle to event
);
复位事件(将事件设置成无信号状态)
BOOL ResetEvent(
HANDLE hEvent //handle to event
);
关闭事件
CloseHandle(HANDLE hEvent);
小心事件的死锁
例子:
#include <Windows.h>
#include <stdio.h>
HANDLE g_hEvent = 0; //获得事件句柄
DWORD CALLBACK PrintProc(LPVOID param){
while(1){
WaitForSingleObject(g_hEvent,INFINITE);
ResetEvent(g_hEvent);
printf("*********\n");
}
return 0;
} DWORD CALLBACK CtlProc(LPVOID param){
while(1){
Sleep(1000);
SetEvent(g_hEvent);
}
return 0;
}
int main(){
g_hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
DWORD pid = 0;
HANDLE hThread[2] = {0};
hThread[0] = CreateThread(NULL,0,PrintProc,NULL,0,&pid);
hThread[0] = CreateThread(NULL,0,CtlProc,NULL,0,&pid);
WaitForMultipleObjects(2,hThread,TRUE,INFINITE);
getchar();
CloseHandle(g_hEvent);
return 0;
}
5.4 信号量
相关的问题
类似于事件,解决通知的相关问题。但提供一个计数器,可以设置次数。
信号量的使用
创建信号量
HANDLE CreateSemaphore(
LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, //安全属性
LONG lInitialCount, //初始化信号量数量
LONG lMaximumCount, //信号量的最大值
LPCTSTR lpName //命名
); 创建成功返回信号量句柄
等候信号量
WaitFor... 每等候通过一次,信号量的信号减1,直到为0阻塞
给信号量指定计数值
BOOL ReleaseSemaphore(
HANDLE hSemaphore, //信号量句柄
LONG lReleaseCount, //释放数量
LPLONG lpPreviousCount //释放前原来信号量的数量,可以为NULL
);
关闭句柄
CloseHandle(HANDLE handle);
#include <Windows.h>
#include <stdio.h>
HANDLE g_hSema = 0; //信号量句柄
DWORD CALLBACK TestProc(LPVOID param){
while(1){
WaitForSingleObject(g_hSema,INFINITE);
printf("*********\n");
}
return 0;
} int main(){
g_hSema = CreateSemaphore(NULL,3,10,NULL);
DWORD pid = 0;
HANDLE hThread = CreateThread(NULL,0,TestProc,NULL,0,&pid);
getchar();
ReleaseSemaphore(g_hSema,5,NULL);
WaitForSingleObject(hThread,INFINITE);
CloseHandle(g_hSema);
return 0;
}
Windows线程开发的更多相关文章
- Kinect for Windows SDK开发入门(15):进阶指引 下
Kinect for Windows SDK开发入门(十五):进阶指引 下 上一篇文章介绍了Kinect for Windows SDK进阶开发需要了解的一些内容,包括影像处理Coding4Fun K ...
- Windows Phone开发(46):与Socket有个约会
原文:Windows Phone开发(46):与Socket有个约会 不知道大家有没有"谈Socket色变"的经历?就像我一位朋友所说的,Socket这家伙啊,不得已而用之.哈,S ...
- windows 驱动开发入门——驱动中的数据结构
最近在学习驱动编程方面的内容,在这将自己的一些心得分享出来,供大家参考,与大家共同进步,本人学习驱动主要是通过两本书--<独钓寒江 windows安全编程> 和 <windows驱动 ...
- C# Windows服务开发从入门到精通
一.课程介绍 大家都知道如果想要程序一直运行在windows服务器上,最好是把程序写成windows服务程序:这样程序会随着系统的自动启动而启动,自动关闭而关闭,不需要用户直接登录,直接开机就可以启动 ...
- Windows线程+进程通信
一 Windows线程进程 1)定义 按照MS的定义, Windows中的进程简单地说就是一个内存中的可执行程序, 提供程序运行的各种资源. 进程拥有虚拟的地址空间, 可执行代码, 数据, 对象句柄集 ...
- Windows内核开发-4-内核编程基础
Windows内核开发-4-内核编程基础 这里会构建一个简单但是完整的驱动程序和一个客户端,部署内核执行一些平时user下无法执行的操作. 将通过以下内容进行讲解: 1 介绍 2 驱动初始化 3 Cr ...
- C++第三十三篇 -- 研究一下Windows驱动开发(一)内部构造介绍
因为工作原因,需要做一些与网卡有关的测试,其中涉及到了驱动这一块的知识,虽然程序可以运行,但是不搞清楚,心里总是不安,觉得没理解清楚.因此想看一下驱动开发.查了很多资料,看到有人推荐Windows驱动 ...
- Windows内核开发-5-(2)-内核模式调试
Windows内核开发-5-(2)-内核模式调试 普通用户模式的调试,采取的是给进程添加一个线程来挂起断点,作为一个调试器的线程在进程中使用.照这样来类推,对操作系统调试相当于添加一个进程来限制操作系 ...
- Windows内核开发-6-内核机制 Kernel Mechanisms
Windows内核开发-6-内核机制 Kernel Mechanisms 一部分Windows的内核机制对于驱动开发很有帮助,还有一部分对于内核理解和调试也很有帮助. Interrupt Reques ...
- Windows内核开发-10-监听对象
Windows内核开发-10-监听对象 Windows内核除了可以监听进程,线程.dll还可以监听特定的对象和注册表.这里先讲一下监听对象. 监听对象 内核提供了一种可以监听对特定的对象类型的句柄进行 ...
随机推荐
- 生成伪随机数 rand;srand函数
1 相关内容来自鱼c论坛https://fishc.com.cn/forum.php?mod=viewthread&tid=84363&extra=page%3D1%26filter% ...
- Ubuntu 20.04 使用 vlmscd 搭建 KMS 服务端
前言 为了内网系统激活需要,搭建此客户端. 1. 下载二进制文件 打开项目官网:https://github.com/Wind4/vlmcsd 下载项目二进制文件: 选择对应系统和架构 选择性能较好的 ...
- 通过计算巢轻松部署ROS自定义资源
概述 阿里云资源编排服务ROS(Resource Orchestration Service)可以帮助您简化云计算资源的管理.遵循ROS定义的模板规范,您可以定义所需云计算资源的集合及资源间的依赖关系 ...
- Netty源码学习5——服务端是如何读取数据的
系列文章目录和关于我 零丶引入 在前面<Netty源码学习4--服务端是处理新连接的&netty的reactor模式>的学习中,我们了解到服务端是如何处理新连接的,即注册Serve ...
- keil 4 安装教程
一.下载 keil 官网 二.安装教程 1.开始安装 双击安装包,开始安装,直接下一步. 2.勾选同意,下一步 3.选择软件安装路径,下一步 4.填写信息 可以随意填写,下一步. 5.等待安装 6.安 ...
- 机器学习-ROC曲线:技术解析与实战应用
本文全面探讨了ROC曲线(Receiver Operating Characteristic Curve)的重要性和应用,从其历史背景.数学基础到Python实现以及关键评价指标.文章旨在提供一个深刻 ...
- ElasticSearch索引生命周期策略配置(ES TTL)
背景 有些索引数据作为临时数据存放,一段时间后我们希望索引可以自动过期删除,就是常说的TTL(Time To Live)机制 ElasticSearch索引数量过多会占用很多主分片和副本分片,最终导致 ...
- 2023-12-09:用go语言,给你两个整数数组 arr1 和 arr2, 返回使 arr1 严格递增所需要的最小「操作」数(可能为 0)。 每一步「操作」中,你可以分别从 arr1 和 arr2
2023-12-09:用go语言,给你两个整数数组 arr1 和 arr2, 返回使 arr1 严格递增所需要的最小「操作」数(可能为 0). 每一步「操作」中,你可以分别从 arr1 和 arr2 ...
- VScode 中利用virtualenv建立 Python 虚拟环境
! https://zhuanlan.zhihu.com/p/638114885 VScode 建立 Python 虚拟环境 主要目的:创建一个与默认 python 版本不同的 python 虚拟环境 ...
- ja-netfilte-ja-netfilte
title: ja-netfilte date: 2022-10-16 16:13:50.339 updated: 2023-02-07 22:58:50.672 url: https://www.y ...