核心编程6——线程

Note 0:
进程实际是由两个组件组成的:一个进程内核对象和一个地址空间.类似地,线程也由两个组件组成:
一个是线程的内核对象,操作系统用它管理线程.内核对象还是系统用来存放线程统计信息的地方.
一个线程堆栈,用于维护线程执行时所需的所有函数参数和局部变量.
Note 1:
进程是有惰性的.进程从来不执行任何东西,它只是一个线程的容器.线程必然是在某个进程的上下文中创建的,而且会在这个进程内部"终其一生".这意味着线程要在其进程的地址空间内执行代码和处理数据.此外,这些线程还共享内核对象句柄,因为句柄表是针对每一个进程的,而不是针对每一个线程.相较于线程,进程所使用的系统资源更多.其原因在于地址空间.为一个进程创建一个虚拟的地址空间需要大量系统资源.系统中会发生大量的记录活动,而这需要用到大量内存.而且,由于.exe和.dll文件要加载到一个地址空间,所以还需要用到文件资源.另一方面,线程使用的系统资源要少得多.事实上,线程只有一个内核对象和一个堆栈;几乎不涉及记录活动,所以不需要占用多少内存.
Note 2:
线程描述了进程内部的一个执行路径.每次初始化进程时,系统都会创建一个主线程.对于用Microsoft C/C++编译器生成的应用程序,这个线程首先会执行C/C++运行库的启动代码,后者调用入口函数(_tmain或_tWinMain),并继续执行,直至入口函数返回C/C++运行库的启动代码,后者最终将调用ExitProcess.对于许多应用程序来说,这个主线程是应用程序惟一需要的线程.但是,进程也可以创建额外的线程来帮助它们完成自己的工作.

Note 3:
操作系统的Windows Indexing Services(Windows索引服务)创建了一个低优先级的线程.此线程定期醒来.并对硬盘上的特定区域的文件内容进行索引.Windows索引服务极大改进了性能.因为一旦成功建立索引.就不必在每次搜索时都打开、扫描和关闭硬盘上的每一个文件.配合这种索引服务.Microsoft Windows Vista提供了一套高级的搜索功能.

Note 4:
如果想创建一个或
多个辅助线程.只需让一个正在运行的线程调用CreateThread:
HANDLE CreateThread(
PSECURITY_ATTRIBUTES psa,
DWORD cbStackSize,
PTHREAD_START_ROUTINE pfnStartAddr,
PVOID pvParam,
DWORD dwCreateFlags,
PDWORD pdwThreadID);
调用CreateThread时.系统会创建一个线程内核对象.这个线程内核对象不是线程本身.而是一个较小的数据结构.操作系统用这个结构来管理线程.可以把线程内核对象想象为一个由线程统计信息构成的小型数据结构.这与进程和进程内核对象之间的关系是相同的
系统将进程地址空间的内存分配给线程堆栈使用.新线程在与负责创建的那个线程相同的进程上下文中运行.因此.新线程可以访问进程内核对象的所有句柄、进程中的所有内存以及同一个进程中其他所有线程的堆栈.这样一来.同一个进程中的多个进程可以很容易地互相通信.
Note 5:
CreateThread函数是用于创建线程的Windows函数.不过.如果写的是C/C++代码.就绝对不要调用CreateThread.相反.正确的选择是使用Microsoft C++运行库函数_beginthreadex.如果使用的不是Microsoft C++编译器.你的编译器的提供商应该提供类似的函数来替代CreateThread.不管这个替代函数是什么.都必须使用它.

Note 6:
使用链接器的/STACK开关来控制线程堆栈使用多少地址空间.如下所示:
/STACK:[reserve] [,commit]
reserve参数用于设置系统将为线程堆栈预留多少地址空间.默认是1 MB(在Itanium芯片组上.默认大小为 4 MB).commit参数指定最初应为堆栈的保留区域提交多少物理存储空间.默认是1页.随着线程中的代码开始执行.需要的存储空间可能不止1页.如果线程溢出它的堆栈.会产生异常.(有关线程堆栈和堆栈溢出异常的详情.请参见第16章.有关常见异常处理的详情.请参见第23章.)系统将捕获这种异常.并将另一个页(或者为commit参数指定的任何大小)提交给保留空间.这样一来.线程堆栈就可以根据需要动态地增大.
Note 7:
保留空间的容量设定了堆栈空间的上限.这样才能捕获代码中的无穷递归bug.例如.假设你写了一个函数以递归方式调用其自身.而且这个函数存在一个bug.会导致无穷递归.每次此函数调用自身时.都会在内存堆栈上创建一个新的堆栈帧.如果系统没有设定堆栈空间的上限.这个递归调用的函数就永远不会终止调用自身.进程的所有地址空间都会被分配出去.大量物理存储会提交给堆栈.通过设置堆栈空间的上限.可以防止应用程序耗尽物理内存区域.而且还可以尽早察觉程序中的bug.
Note 8:
创建多个线程时.可以让它们使用同一个函数地址作为起点.这样做完全合法.而且非常有用.(可以传递了不同的pvParam值,来区分不同的线程所调用相同的函数.)

Note 9:
TerminateThread函数是异步的.也就是说.它告诉系统你想终止线程.但在函数返回时.并不保证线程已经终止了.如果需要确定线程已终止运行.还需要调用WaitForSingleObject或类似的函数.并向其传递线程的句柄.
Note 10:
如果通过返回或调用ExitThread函数的方式来终止一个线程的运行.该线程的堆栈也会被销毁.但是.如果使用的是TerminateThread.那么除非拥有此线程的进程终止运行.否则系统不会销毁这个线程的堆栈.Microsoft故意以这种方式来实现TerminateThread.否则.假如其他还在运行的线程要引用被"杀死"的那个线程的堆栈上的值.就会引起访问冲突.让被"杀死"的线程的堆栈保留在内存中.其他的线程就可以继续正常运行.
此外.动态链接库(DLL)通常会在线程终止运行时收到通知.不过.如果线程是用TerminateThread强行"杀死"的.则DLL不会收到这个通知.其结果是不能执行正常的清理工作.
Note 11:
线程终止运行时.会发生下面这些事情:
线程拥有的所有用户对象句柄会被释放.在Windows中.大多数对象都是由包含了"创建这些对象的线程"的进程拥有的.但是.一个线程有两个User对象:窗口(window)和挂钩(hook).一个线程终止运行时.系统会自动销毁由线程创建或安装的任何窗口.并卸载由线程创建或安装的任何挂钩.其他对象只有在拥有线程的进程终止时才被销毁.
线程的退出代码从STILL_ACTIVE变成传给ExitThread或TerminateThread的代码.
线程内核对象的状态变为signaled.
如果线程是进程中的最后一个活动线程.系统认为进程也终止了.
线程内核对象的使用计数递减1.

Note 19:
对CreateThread函数的一个调用导致系统创建一个线程内核对象.该对象最初的使用计数为2.(除非线程终止,而且从CreateThread返回的句柄关闭,否则线程内核对象不会被销毁.)该线程内核对象的其他属性也被初始化:暂停计数被设为1,退出代码被设为STILL_ACTIVE (0x103),而且对象被设为nonsignaled状态.
Note 20:
一旦创建了内核对象,系统就分配内存,供线程的堆栈使用.此内存是从进程的地址空间内分配的,因为线程没有自己的地址空间.然后,系统将两个值写入新线程堆栈的最上端.(线程堆栈始终是从高位内存地址向低位内存地址构建的.)写入线程堆栈的第一个值是传给CreateThread函数的pvParam参数的值.紧接在它下方的是传给CreateThread函数的pfnStartAddr值.
Note 21:
每个线程都有其自己的一组CPU寄存器,称为线程的上下文(context).上下文反映了当线程上一次执行时,线程的CPU寄存器的状态.线程的CPU寄存器全部保存在一个CONTEXT结构(在WinNT.h头文件中定义).CONTEXT结构本身保存在线程内核对象中.
Note 22:
当线程的内核对象被初始化的时候,CONTEXT结构的堆栈指针寄存器被设为pfnStartAddr在线程堆栈中的地址.而指令指针寄存器被设为RtlUserThreadStart函数(该函数未见于正式文档)的地址,此函数是NTDLL.dll模块导出的.
RtlUserThreadStart函数的基本用法如下:
VOID RtlUserThreadStart(PTHREAD_START_ROUTINE pfnStartAddr, PVOID pvParam) {
__try {
ExitThread((pfnStartAddr)(pvParam));
}
__except(UnhandledExceptionFilter(GetExceptionInformation())) {
ExitProcess(GetExceptionCode());
}
// NOTE: We never get here.
}
Note 23:
线程完全初始化好之后,系统将检查CREATE_SUSPENDED标志是否传给CreateThread函数.如果此标记没有传递,系统将线程的暂停计数递增至0;随后,线程就可以调度给一个处理器去执行.然后,系统在实际的CPU寄存器中加载上一次在线程上下文中保存的值.现在,线程可以在其进程的地址空间中执行代码并处理数据了.
Note 24:
新线程执行RtlUserThreadStart函数的时候,将发生以下事情:
围绕你的线程函数,会设置一个结构化异常处理(Structured Exception Handling,SEH)帧.这样一来,线程执行期间所产生的任何异常都能得到系统的默认处理.
系统调用你的线程函数,把你传给CreateThread函数的pvParam参数传给它.
线程函数返回时,RtlUserThreadStart调用ExitThread,将你的线程函数的返回值传给它.线程内核对象的使用计数递减,而后线程停止执行.
如果线程产生了一个未被处理的异常,RtlUserThreadStart函数所设置的SEH帧会处理这个异常.通常,这意味着会向用户显示一个消息框,而且当用户关闭此消息框时,RtlUserThreadStart会调用ExitProcess来终止整个进程,而不只是终止有问题的线程.
Note 25:
当RtlUserThreadStart开始执行时,它会调用C/C++运行库的启动代码,后者初始化继而调用你的_tmain或_tWinMain函数.你的入口函数返回时,C/C++运行时启动代码会调用ExitProcess.所以对于C/C++应用程序来说,主线程永远不会返回到RtlUserThreadStart函数.
Note 26:
Visual Studio附带了4个原生的C/C++运行库,还有2个库面向Microsoft.NET的托管环境.注意,所有这些库都支持多线程开发:不再有单独的一个C/C++库专门针对单线程开发.下面对这些库进行了描述.
Microsoft Visual Studio附带的C/C++库
库名称      描述
LibCMt.lib   库的静态链接Release版本
LibCMtD.lib 库的静态链接Debug版本
MSVCRt.lib   导入库,用于动态链接MSVCR80.dll 库的Release版本. (这是新建项目时的默认库)
MSVCRtD.lib 导入库,用于动态链接MSVCR80D.dll库的Debug版本
MSVCMRt.lib 导入库,用于托管/原生代码混合
MSVCURt.lib 导入库,编译成百分之百纯MSIL代码

-------------------------------------------------------------------

 

 

转载于:https://www.cnblogs.com/lzjsky/archive/2010/06/04/1751719.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/276046.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PHP解决抢购、秒杀、抢楼、抽奖等阻塞式高并发库存防控超量的思路方法

转载链接:http://www.4u4v.net/thinking-approach-to-buy-spike-grab-floor-sweepstakes-and-other-high-concurrent-blocking-prevention-excess-inventory-solve-php.html 如今在电商行业里,秒杀抢购活动已经是商家常用促销手段。但是库存数量有限,而同…

看了就会的 Node.js 三大基础模块常用 API

大家好,我是若川。欢迎加我微信 ruochuan12,加群交流学习。今天分享一篇nodejs基础的文章。点击下方卡片关注我,或者查看源码等系列文章。在日常使用 Node 进行开发的时候,会使用到一些文件系统、路径操作等基础 API,这…

vue-cli3插件初体验

vue-cli3发布自2018年8月,距离现在还不是特别久,最好搭建项目刚好用到,所以写下这篇文章,记录一下踩坑经历。vue的作者说过,vue-cli的本质是模版的拉取,太多的配置导致了模版的难以维护,所以重构…

ios设计登录功能_亲爱的产品设计师,这是iOS 14的新功能

ios设计登录功能On June 22, 2020 Apple previewed iOS 14 for the first time. As always there are quite some changes you should know about as a product designer like widgets, pickers, app clips, permissions and more.2020年6月22日,Apple首次预览iOS 1…

c++ int 转 short_C/C++结构体内存对齐

在面试或工作中,经常会遇到内存对齐的问题。这里结合我的理解谈一谈对内存对齐的理解。1. 为什么要内存对齐,不对齐会怎么样?内存中存放数据是为了给CPU使用,CPU访问内存数据时会受到地址总线宽度的限制,也就是一次能从…

对于日访问量达到1W IP的处理方法

转自:http://www.java123.net/56026-2.html 对于日访问量达到1W IP的处理方法 一、1万ip真是不高: 1.常用数据用缓存,减轻数据库压力。 2.详细页数据生成静态页面。 二、10000算是相当小的了,不需要什么特殊的处理机制,只要符合最一般的…

数据契约(DataContract)

WCF第一要素就是契约: 服务契约用于声明可用于远程访问的类型。在Interface或class开始处使用服务契约标签. [ServiceContract] Public interface Iservice { } 接口调用契约的好处: 1. 同一服务类型可以实现多个不相干的服务契约. 2. 有利于版本升级 3. 按照…

jakob slam_Jakob Nielsen针对用户界面设计的第二种可用性启发法

jakob slamIn the pursuit of providing great user experiences, it’s imperative that digital products are evaluated. A 为了提供出色的用户体验,必须对数字产品进行评估。 一个 heuristic evaluation is essential to delivering great user experiences. I…

微软Office 365正式上架Mac App Store

今天,Office 365正式在Mac App Store上架,Mac用户可以轻松下载Word,Outlook,Excel,PowerPoint,OneNote以及整套微软的热门应用程序。用户还可以从应用程序内订购Office 365。苹果全球开发者关系高级主管Sha…

一文搞懂浏览器原理

大家好,我是若川。最近这几年,云计算的普及和 HTML5 技术的快速发展,越来越多的应用转向了浏览器 / 服务器(B/S)架构,这种改变让浏览器的重要性与日俱增,视频、音频、游戏几大核心场景也都在逐渐…

python处理excel可视化_python如何将excel数据处理可视化

python将excel数据处理可视化的方法:首先安装xlrd与xlwt库,进行表格读取;然后使用pyecharts生成Echarts图表的类库;最后安装Echarts读取Excel数据及显示即可。python将excel数据处理可视化的方法:Excel表操作python操作…

dataframe中将一列数据切分成多列

为什么80%的码农都做不了架构师&#xff1f;>>> 原sheet中数据 目的 将【备注】列切分成【key】列和【value】列 Python sheet[key] sheet[备注].str.extract(r(_.*(?\u503c))) sheet[value] sheet[备注].str.extract(r((?<).*))结果 参考 pandas.Series.st…

matplotlib可视化_EDA:Geopandas,Matplotlib和Bokeh中的可视化

matplotlib可视化Nowadays, everyone is immersed with plenty of data from news sources, cellphones, laptops, workplaces, and so on. Data conveys with tons of information from different data variables like date, string, numeric, and geographical format. How t…

(转)结婚那天,妈问我:坐在角落里象两个要饭模样的人是谁?

人人看到的文章 很感人~~~~结婚那天&#xff0c;妈问我&#xff1a;坐在角落里象两个要饭模样的人是谁&#xff1f; 我看过去的时候&#xff0c;有个老头正盯着我&#xff0c;旁边还有个老太太&#xff0c;发现我看着他们时赶忙低下头。我不认识他们但也不象要饭的&#xff0c;…

nginx-1.13.x源码安装

Nginx 安装配置【依赖库】[ zlib ]&#xff08;下载&#xff09;http://download.chinaunix.net/download.php?id24013&ResourceID12241 [ pcre ]apt-get install libpcre-dev[ openssl ]&#xff08;下载&#xff09;http://download.chinaunix.net/download.php?id3937…

小技巧!CSS 整块文本溢出省略特性探究

大家好&#xff0c;我是若川。欢迎加我微信 ruochuan12&#xff0c;长期交流学习。今天的文章很有意思&#xff0c;讲一讲整块文本溢出省略打点的一些有意思的细节。点击下方卡片关注我&#xff0c;或者查看源码系列文章。文本超长打点我们都知道&#xff0c;到今天&#xff08…

linux配置ip地址 suse_SUSE Linux下设置IP的两种方法

第一种SUSE Linux IP设置方法ifconfig eth0 192.168.1.22 netmask 255.255.255.0 uproute add default gw 192.168.1.2释义&#xff1a;#IP配置&#xff0c;包括子网掩码,看情况修改eth0和192.168.1.22#网关修改 ,看情况修改192.168.1.2第二种SUSE Linux IP设置方法在suse操作系…

寒假作业3:抓老鼠啊

7-1 抓老鼠啊~亏了还是赚了&#xff1f; &#xff08;20 分&#xff09; 某地老鼠成灾&#xff0c;现悬赏抓老鼠&#xff0c;每抓到一只奖励10元&#xff0c;于是开始跟老鼠斗智斗勇&#xff1a;每天在墙角可选择以下三个操作&#xff1a;放置一个带有一块奶酪的捕鼠夹(T)&…

笔记本移交_创建完美的设计移交

笔记本移交重点 (Top highlight)Design specifications (specs) are guidelines that developers will use to implement a design. Think of an architect providing building blueprints to the construction team. Many designers think of specs as mindless zombie work. …

大手笔,送¥1599的Apple AirPods Pro和独家礼物等

大家好&#xff0c;我是若川。为感谢公众号读者们长久以来的支持&#xff0c;本次我联合几位前端界大佬给大家送超级福利了。除了联合福利之外&#xff0c;每位前端大佬还带了专属礼品送给大家&#xff0c;所有抽奖均可重复参与、可重复中奖&#xff0c;详情见下文每个公众号的…