- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
关于TLS
?
TLS是“线程局部存储(Thread Local Storage)”的缩写,“Local”这个词有“局部”、“本地”的意思,所以也可以说是“线程本地存储”。顾名思义,这就是局部于唯一的线程、为具体线程所“私用、专用”的存储空间。这里所说的“空间”并不是“用户空间”、“系统空间”那个意义上的空间,而是指用户空间中个别变量、数组、或数据结构所占据的存储空间。
我们知道,线程并不独立拥有用户空间,用户空间是归进程所有,为同一进程中的所有线程所共享的。所以,用户空间中的任何一个区域,只要有一个线程可以访问,那么同一进程中的所有其它的线程就都能访问。在这个意义上,整个用户空间都是(由同一进程中的)所有线程共享的,不存在只归一个线程使用的变量或数据结构。可是,一般而言,程序对变量或数据结构的访问都是按变量名访问的,经过编译/连接之后就是按地址访问,要是不知道一个变量的地址,实际上就无法正常和正确地加以访问(“地毯式”的扫描一般而言无法辨认数据的边界,所以无法正确读取其内容)。在这个意义上,则只归一个线程使用的变量或数据结构又是可能的。
注意TLS只是对全局量和静态变量才有意义。局部量存在于具体线程的堆栈上,而每个线程都有自己的堆栈,所以局部量本来就是“局部”于具体线程的。至于通过动态分配的缓冲区,则取决于保存着缓冲区指针的变量。如果缓冲区指针是全局量,那么同一进程中的所有线程都能访问这个缓冲区;而若是局部量,则别的线程自然就不得其门而入。
?
那么为什么需要有全局变量(或静态变量)的TLS呢?
对于TLS的用途,Unix/Linux的C程序库libc中的全局变量errno是个最典型的例子。
?
if (open (filename, mode) 0)
{
????error (0, errno, %s, infile);
????. . . . . .
}
?
当系统调用从内核返回用户空间时,如果EAX的值为0xfffff001至0xffffffff之间即为出错,取其负值(2的补码)就是出错代码。此时将出错代码写入一个全局量errno,以供进一步查验,并将EAX的值改成-1。这就是从Unix时代初期就定下的对于返回整数的系统调用的约定。其好处是写程序时可以略微方便一些,不用每次都在函数中定义一个局部变量err,再写成“if ((err=open(filename, mode)) 0”、并因为系统调用出错返回的几率毕竟很小。
在线程的概念出现之前,或者说在一个进程只含有一个线程的时代,这样安排不会有什么问题。这是因为,从启动系统调用的C库函数把出错代码写入全局量errno以后,到调用者发现返回值为-1、因而从errno获取出错代码的这一段时间中errno的值不可能改变。即使在这中间发生了中断、并且导致进程调度,从当事进程的角度看也只是时间上的短暂停滞,却不会有谁来改变errno的内容;因为全局量errno是归进程所有,别的进程不会来打扰。
但是,有了多线程的概念和技术以后,情况就不一样了。因为同一进程中的多个线程是共享一个用户空间的,如果几个线程的程序中都引用全局量errno,那么它们在运行中实际访问的就是同一个地址。为说明问题,我们且假定线程T1和T2属于同一进程,再来考察下述的假想情景:
1.?????????T1先通过C库函数open()进行系统调用,但是因为所给定的文件名实际上是个目录,所以内核返回出错代码EISDIR。这个出错代码被写入了全局量errno。
2.?????????T1发现open()的返回值为-1,因而需要以errno当时的值、即出错代码为参数调用error();但是,在T1还没有来得及从errno读出之前就发生了中断,而且导致线程调度,调度的结果是线程T2获得运行;
3.?????????T2通过C库函数signal()启动另一次系统调用,但是因为使用参数不当而出错,内核返回的出错代码为EINVAL,表示参数无效。这个出错代码也被写入全局量errno,于是errno的值变成了EINVAL。
4.?????????T2从全局量errno读取出错代码,并依此进行相应的(正确)处理。但是errno的值仍保持为EINVAL,此后T2没有再进行系统调用。
5.?????????一段时间之后,T1又被调度运行,继续其原有的处理,即从errno读出、并以errno的值为参数调用error()。但是,errno的值原来是EISDIR,而现在已变成EINVAL。
?
由此可见,在多线程的环境下,对于某些应用,由多个线程共享一个同名的全局量是有问题的。
怎么解决呢?使用局部量当然是个办法,例如改成“if ((err=open(filename, mode)) 0”,这似乎轻而易举地就解决了问题。可是,不幸的是,
您可能关注的文档
最近下载
- 降低护士临时用药时PDA漏扫率 (2).pptx VIP
- (必会)公路水运工程试验检测师《水运结构与地基》近年考试真题题库(含答案解析).docx VIP
- 拓展训练的项目坎坷人生路.doc VIP
- 盐膏层防漏堵漏施工技术在亚速尔哲别油田的应用.doc VIP
- 公路水运工程试验检测师《水运结构与地基》考试题及答案.doc VIP
- 吴永平传染病布鲁氏杆菌讲课文档.ppt VIP
- 土库曼斯坦亚速尔地区盐膏层及高压盐水层钻井液技术措施.docx VIP
- 2024年德惠市招聘社区工作者真题.docx VIP
- 医学科研方向研究进展汇报.pptx
- 2025年职业资格公路水运检测师水运结构与地基-水运结构与地基参考题库含答案解析(5套).docx VIP
文档评论(0)