文档章节

SylixOS中pthread_cancel浅析

J
 Jackstraw瑞
发布于 2017/02/06 13:16
字数 2125
阅读 6
收藏 0

1.知识简介

1.1 概述

       取消一个线程要确保该线程能够释放其所持有的任何锁、分配的内存,使整个系统保持一致性。在很多情况下要保证这种正确性是有一定困难的。

       一种简单的线程取消:取消线程调用一个取消线程的函数,被取消线程死亡。在这种情况下,被取消线程所持有的的资源得不到释放。取消线程负责保证被取消者处于可安全取消状态,在一个要求可靠性高的系统中,这种保证非常困难或者无法实现。这种取消称为不受限制的异步取消

       还存在另外一种更安全的线程取消机制。一个线程可以以可靠的受控制的方式向进程的其他线程发出取消请求,目标线程可以挂起这一请求使实际的取消动作在此后安全的时候进行,称为延迟取消。目标线程还可以定义其被取消后自动被系统调用的线程清除函数。

       SylixOS兼容绝大多数POSIX接口, SylixOS中pthread_cancel函数执行线程取消功能。

       pthread_cancel 函数和目标线程的取消动作是异步的。根据目标线程的取消属性不同,取消请求可能被忽略、立即执行或者延迟处理。为了清楚这些动作,下面知识点先简单介绍线程取消属性相关概念。

1.2 知识点

       SylixOS中pthread_cancel函数由px_othread.h头文件定义,其原型为:

        int  pthread_cancel (pthread_tthread);

  •       此函数成功返回 0,失败返回错误号;
  •       参数 thread 是取消的线程句柄。

 

      SylixOS中用取消状态,取消类型和取消请求这3个元素共同表示一个线程的取消属性,其存在于线程控制块中。如表2‑1所示。

表2‑1  取消说明

       线程初始化时会有默认的取消属性,即线程保留允许取消延迟取消的属性,保证收到取消信号时,线程接受该取消信号,不会屏蔽掉,并且会在自身安全的时候,调用线 程删除函数,即延迟取消。另外一个线程的取消状态和取消类型可分别调用相关函数设置,如表 2‑2所示。函数均在px_pthread.h头文件中定义。

表2‑2  设置取消属性

       前文提到,延迟请求会使线程的取消动作在安全的时候进行,那线程具体的取消时机是在什么时候呢?会涉及到“取消点”的概念,在后续章节中介绍。

2.技术实现

2.1 实现流程

       SylixOS中pthread_cance函数实现机制,如图3‑1所示。

图3‑1  pthread_cancel函数实现流程

2.2 取消点概念

       在使用延迟取消机制时,一个线程在可以被取消的地方定义取消点,当收到取消请求时,被取消的线程执行到取消点时退出,或者在一个取消点调用被阻塞时退出。

       由于在延迟取消中必须在取消点才能被取消,这一限制可能使取消请求被挂起任意长时间。因此,如果某个调用可能使线程被阻塞或者进入某个较长时间的过程, POSIX 要求这些调用属于一个取消点,或者称这些调用为取消点调用,以防止取消请求陷入长时间等待,SylixOS中存在一些拥有取消点的函数,如open,read,pthread_join,printf等,他们都直接或间接的调用了pthread_testcancel函数, pthread_testcancel函数内部实现流程如图 3‑2所示。

图3‑2  pthread_testcancel函数实现流程

       因此,被取消线程会在执行拥有取消点的函数时,进入到pthread_testcancel函数内部,进行如图 3‑2所示的允许取消、延迟取消以及取消请求标志的判断流程,倘若条件满足,被取消线程会在这里调用线程删除函数删除自身。

       表 3‑1列出部分拥有取消点的函数以供参考。

表3‑1  拥有取消点的函数

3 示例演示

       以下示例验证均在SylixOS环境下进行。

3.1 示例1:立即取消

       如图 4‑1所示,子线程设置立即取消类型,那么主线程成功发送取消信号后,打印“pthread_cancel OK”,子线程会在下次执行开始处删除自身,退出时子线程i的值可能为0~1000000任意值。

图4‑1  立即取消示例

3.2 示例2:延迟取消

       如图 4‑2所示,子线程设置延迟取消类型,那么主线程执行取消线程函数后,打印“pthread_cancel OK”,子线程会在执行到取消点时删除自身,sleep为拥有取消点的函数,因此子线程退出时i 的值一定为1000000。(即pthread_cancel函数成功返回并不能代表目标线程已经退出)

图 4‑2  延迟取消示例

       倘若示例1和示例2都把子线程中入口函数中的sleep(1)这条语句去掉,那么示例1中的立即取消仍然有效;示例2中的延迟取消虽然主线程打印“pthread_cancel OK”,但是因为子线程的while(1)循环里没有“取消点”,子线程的取消请求一直都不能被处理,因此子线程并不会被成功取消,而是继续循环运行。如图 4‑3所示。

图4‑3  没有“取消点”

       不过我们可以手动加入pthread_testcancel函数进行取消请求处理,这样子线程也就有了一个“取消点”,在“取消点”取消请求被处理,线程即可退出。如图 4‑4所示。

图4‑4  pthread_testcancel处理取消请求

4. 总结

       立即取消会通过信号方式修改目标线程任务上下文环境,即把旧目标线程任务上下文做适当偏移,将信号处理句柄安装在上下文开始处,组成新的目标线程任务上下文,当任务调度轮到目标线程执行时,目标线程会优先执行信号处理程序,完成信号请求的动作。这里要注意时任务调度之后立即取消,因为任务调度切换任务上下文会花费一些时间,所以立即取消并不代表时间上的“立刻”。

       延迟取消仅仅使目标线程的线程控制块相关标志修改,在目标线程执行到相关拥有取消点的函数时,进行取消请求检查,满足条件才会删除线程。即任务调度之后,目标线程还会继续执行任务上下文指定任务,直到碰到“取消点”,才可能取消线程。

       pthread_cancel的成功返回仅仅表明调用该函数的线程完成了对目标线程线程控制块相关标志的修改,等到任务调度,目标线程才会检查这些标志,做出相应处理,即pthread_cancel的成功返回并不能代表目标线程的完全取消。

       由此可见,线程取消并不是安全的,立即取消会让目标线程“立即退出”,延迟取消会给目标线程从开始到“取消点”争取一段执行时间,如果没有“取消点”,目标线程就不能完成预期的线程取消动作,这些都有可能造成很多不安全的因素,目标线程取消之前占有的资源如互斥锁,互斥锁没有释放线程就退出了,将导致别的线程无法获得改锁从而一直阻塞,更严重的还会造成死锁现象。

       线程可以安排它退出时调用线程清理处理程序,通过pthread_cleanup_pop和pthread_cleanup_push函数可以将有些“后事”在线程退出后交给线程清理处理程序帮忙处理,本文档此次主要浅析SylixOS的pthread_cancel流程,就不对线程清理处理程序如何使用做详细介绍了。

5. 参考资料

       SylixOS内核源码

     《SylixOS应用程序开发手册》

© 著作权归作者所有

J
粉丝 2
博文 8
码字总数 10375
作品 0
南京
私信 提问
SylixOS线程堆栈大小浅析

目录 1. SylixOS线程、线程栈介绍 1 1.1 线程的介绍 1 1.2 线程栈的介绍 1 2. SylixOS线程栈大小的分配 1 2.1 线程、线程栈相关属性的设置 2 2.2 线程栈大小 2 2.3 线程堆栈警戒区 3 3. 总结...

Esc120
2018/06/26
0
0
SylixOS-IgH系统平台搭建

1.参考手册 下面7个文件存放在本地服务器“\10.9.1.113.研发部9.ExchangeFolder郑磊”路径下 《RealEvo-IDE使用手册》 《SylixOS应用开发手册》 《SylixOSshell用户手册》 《SylixOS-IgH使用...

zhengleich
2018/05/15
0
0
SylixOS上EtherCAT实现

1 EtherCAT开源协议栈介绍 目前常见开源的主站代码为RT-LAB开发的SOEM(Simple OpenSource EtherCAT Master)和EtherLab的the IgH EtherCAT® Master,SylixOS对两者都支持。其中IgH作为常用的...

Jackstraw瑞
2017/11/01
0
0
VxWorks驱动移植至SylixOS总结

本文档描述了将VxWorks中的驱动源码快速移植至SylixOS中的方法,使用时需要结合SylixOS中的VxWorks兼容层实现。 1. 驱动注册与初始化 1.1 VxWorks中驱动注册与初始化 1.1.1 初始化函数 VxWo...

zhywxyy
2018/08/21
0
0
SylixOS调试方法详解——性能分析

1. SylixOS调试方法介绍 SylixOS实现了一个功能强大的调试stub(桩),可在设备或模拟器上在线调试应用程序,RealEvo-IDE也提供配套的调试插件。目前RealEvo-IDE既支持自动推送调试、也支持传...

Esc120
2018/06/26
0
0

没有更多内容

加载失败,请刷新页面

加载更多

分布式Session的实现方式

JWT Token 使用 JWT Token 储存用户身份,然后再从数据库或者 cache 中获取其他的信息。这样无论请求分配到哪个服务器都无所谓。 Tomcat + Redis 在 tomcat 的配置文件中配置: <Valve class...

禅明
9分钟前
0
0
Android饼图 PieChart

PieChart 饼图,android 图表。会根据定义PieChartView的大小自动居中,所以如果要调整位置,只需要在xml更改PieChartView位置大小即可。 https://github.com/ccMagic/PieChart 1、先看一下效...

ccMagic
13分钟前
1
0
说说我当初是如何学Linux的

今天我就说说我当初是如何从一名普通桌面维护工程师,通过学习和努力转成Linux运维工程师的,以及作为Linux运维工程师需要一些什么技能和知识,希望可以帮到一些对Linux有兴趣或者想往Linux...

Linux就该这么学
14分钟前
1
0
Tomcat启动异常Unable to register MBean [HikariDataSource (null)]:InstanceAlreadyExistsException

Unable to register MBean [HikariDataSource (null)] with key 'xxx'; nested exception is javax.management.InstanceAlreadyExistsException: com.zaxxer.hik ari:name=baseDataSource,ty......

sunranhou
19分钟前
1
0
qt从普通线程发信号到UI线程

加入从当前一个普通线程发送信号到ui,更新Ui只能使用Qt::BlockingQueuedConnection,用Qt::QueuedConnection会一会有用一会没用,并且会导致崩溃。 connect(this, &Task::startTask, this, ...

青黑
40分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部