关于pthread_cancel()的运用,取消点的理解
关于pthread_cancel函数的运用
- 一、相关简介
- 1、取消点:
- 2、cancelstate
- 3、canceltype
- 二、有关函数
- 1、线程创建函数 create
- 2、线程终止函数 cancel
- 3、线程终止状态 cancelstate
- 4、线程终止类型 canceltype
- 三、实践
- 1、全部默认
- (1)no cancel
- (2)cancel
- 2、state设置
- state==PTHREAD_CANCEL_DISABLE
- 3、type设置
- type==PTHREAD_CANCEL_ASYNCHRONOUS
一、相关简介
1、取消点:
我们都知道,程序的进行是一个时间过程而不是一个时间点。取消点的简单意思来说:
在一个时间段内,程序被挂起时,可以被取消的一个时间点。(APUE363页有详细的取消点函数)
也就是说,当线程出现 block(阻塞) 时,这个被阻塞的地方就是可被取消的地方。
更通俗的来说:就是线程A执行过程中,如果遇到其他线程B执行cancel函数,
线程继续运行,直到线程某一行代码出现阻塞
(如:pthread_testcancel、pthread_join、pthread_cond_wait、printf、sleep、read、write、等都是可以产生阻塞的函数)
此时就会退出。如果线程B还使用了pthread_join去获取返回值,返回值为整型且为PTHREAD_CANCELED(-1)
2、cancelstate
上诉的第3个函数pthread_setcancelstate是可以改变线程遇到cancel信号的状态。
一共有两种状态:
1、对cancel信号有反应(默认)
2、不理会cancel信号
3、canceltype
上诉第4个函数pthread_setcanceltype是可以改变线程终止类型
前提是cancelstate为enable
也是一共两个状态:
1、等到取消点再终止。(默认)
2、直接终止。
二、有关函数
1、线程创建函数 create
@thread:线程标识符
@attr:线程属性,传递NULL为默认属性
@start_routine:建立的新线程的函数指针
@arg:线程的参数
return:成功返回0,错误返回errno,且thread不定义EAGAIN:资源不足创建新线程EINVAL:输入无效的线程属性EPERM:无权限设置调度策略和线程属性参数即attr
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
2、线程终止函数 cancel
@thread:需要终止的线程标识号
return:成功返回0 错误返回errnoESRCH:错误的线程号
int pthread_cancel(pthread_t thread);
默认情况下,使用cancel函数后,线程并不会立刻终止。在关闭一个线程中,有两个重要的点是:
3、线程终止状态 cancelstate
@state:PTHREAD_CANCEL_ENABLE:线程对cancel信号立即有反应,将设置为CANCEL状态 (默认)PTHREAD_CANCEL_DISABLE:如果线程state为不可取消,线程不理会信号,继续执行,而使用cancel函数的线程会一直阻塞到可取消状态@oldstate:NULL:state写入有效,即当前只想设置属性,而不关心原来的属性不为NULL:state不写入,保持原有的设定,且获取原来的属性return:成功返回0,错误返回errno EINVAL:无效的state
int pthread_setcancelstate(int state,int *oldstate)
4、线程终止类型 canceltype
@type:PTHREAD_CANCEL_DEFERRED:运行到下一个取消点就退出 (默认)PTHREAD_CANCEL_ASYNCHRONOUS:直接退出@oldtyoe:NULL:type写入有效,即当前只想设置属性,而不关心原来的属性不为NULL:type不写入,保持原有的设定,且获取原来的属性return:成功返回0,错误返回errno EINVAL:无效的type
int pthread_setcanceltype(int type,int *oldtype)
三、实践
有了上一章的简介,现在来实际操作一下。
1、全部默认
(1)no cancel
线程:
void *pt1(void*p)
{ int *num=p;while(--(*num)>100)if(*num==1000)printf("block\n");return NULL;
}
main函数:
void main(void)
{int val=65535;pthread_t p1;pthread_create(&p1,NULL,pt1,&val);pthread_join(p1,NULL);printf("join p1:%d\n",val );
}
输出:当 *num等于1000时打印阻塞,但是线程继续执行到 *num=100
block
join p1:100
(2)cancel
在创建进程后立刻cancel掉进程,由于进程运行速度过快,添加了一些运算减缓线程运行速度。
线程:
void *pt1(void*p)
{ int *num=p;while(--(*num)>100)if(*num==1000)printf("block\n");return NULL;
}
main:
void main(void)
{int val=65535;pthread_t p1;pthread_create(&p1,NULL,pt1,&val);pthread_cancel(p1);pthread_join(p1,NULL);printf("join p1:%d\n",val );
}
输出:当 *num==1000时,打印信息产生阻塞,也就是取消点为printf函数,线程在此时退出
block
join p1:1000
2、state设置
state==PTHREAD_CANCEL_DISABLE
线程:
void *pt1(void*p)
{ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);int *num=p;while(--(*num)>100)if(*num==1000)printf("block\n");return NULL;
}
main:
void main(void)
{int val=65535;pthread_t p1;pthread_create(&p1,NULL,pt1,&val);pthread_cancel(p1);pthread_join(p1,NULL);printf("join p1:%d\n",val );
}
输出结果与无cancel相同,线程不理会cancel信号、
3、type设置
前提都是state为enable状态
type==PTHREAD_CANCEL_ASYNCHRONOUS
void *pt1(void*p)
{ pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);int *num=p;while(--(*num)>100)if(*num==1000)printf("block\n");return NULL;
}
main:
void main(void)
{int val=65535;pthread_t p1;pthread_create(&p1,NULL,pt1,&val);pthread_cancel(p1);pthread_join(p1,NULL);printf("join p1:%d\n",val );
}
输出:type修改为异步类型,只要收到cancel信号,立马结束线程
多种可能 取决于运行速度
join p1:34474
join p1:29783
join p1:39144
关于pthread_cancel()的运用,取消点的理解相关推荐
- 线程取消pthread_cancle、取消选项
目录 pthread_cancel 杀死(取消)线程 取消选项 ① 可取消状态:PTHREAD_CANCLE_ENABLE.PTHREAD_CANCLE_DISABLE ②取消类型(推迟取消):PTH ...
- linux线程(互斥锁、条件)
线程概念: 典型的UNIX/Linux进程可以看成只有一个控制线程:一个进程在同一时刻只做一件事情.有了多个控制线程后,在程序设计时可以把进程设计成在同一时刻做不止一件事,每个线程各自处理独立的任务. ...
- linux学习笔记 -- 系统编程
系统编程 相关概念 概念 简易cpu结构 mmu内存管理单元 环境变量 PATH SHELL HOME LANG TERM getenv setenv unsetenv 进程控制 fork函数 get ...
- Linux多线程概念及实现
目录 一.Linux线程基本概念 1.什么是线程 2.页表的映射 3.线程优点 4.线程缺点 5.线程异常 6.线程用途 二.Linux线程vs进程 1.线程和进程 2.进程的多个线程共享资源 3.进 ...
- Linux系统编程--守护进程、线程
守护进程 Daemon(精灵)进程,是 Linux 中的后台服务进程,通常独立于控制终端并且周期性地执行某种任务或 等待处理某些发生的事件.一般采用以 d 结尾的名字. Linux 后台的一些系统服务 ...
- Linux(九)线程控制
对于线程的操作接口(创建.终止.等待.分离) Linux下线程的操作接口,其实都是库函数,因为linux操作系统并没有直接向上层提供线程的系统调用接口,因此大佬们就基于系统调用接口封装实现了线程的相关 ...
- Linux tcpdump命令详解与Wireshark
简介 用简单的话来定义tcpdump,就是:dump the traffic on a network,根据使用者的定义对网络上的数据包进行截获的包分析工具. tcpdump可以将网络中传送的数据包的 ...
- Linux 常用命令标记
1.linux 服务器之间拷贝文件 scp 本地用户名@IP地址:文件名1 远程用户名@IP地址:文件名2 该命令可以变型为目的服务器204上输入如下命令:红色部分是需要接受目的地,-r是递归复制该文 ...
- tcpdump的简单选项介绍
tcpdump采用命令行方式,它的命令格式为: tcpdump [ -AdDeflLnNOpqRStuUvxX ] [ -c count ] [ -C file_size ] [ -F file ] ...
- Linux tcpdump命令
一.简介 用简单的话来定义tcpdump,就是:dump the traffic on a network,根据使用者的定义对网络上的数据包进行截获的包分析工具. tcpdump可以将网络中传送的数据 ...
最新文章
- 关于微服务的7个疑问和解答!
- 彻底给你讲清楚分布式事务原理
- AI Studio中的视觉数据集合
- win10+ubuntu双系统下,ubuntu不能访问windows的磁盘分区
- 算法与数据结构(python):递归
- 仿as3的displaylist
- OpenVINO 2019 R2.0 Custom Layer Implementation for linux(2)
- app传输数据到php,安卓app客户端和使用php的服务器端数据交互
- 金蝶移动bos开发教程_求助临沂金蝶k3,kis,eas软件各版本优势
- Downie 4 for Mac(视频下载)
- Android 滑动界面实现---Scroller类别 从源代码和开发文档了解(让你的移动布局)...
- NV21数据的镜像算法
- 数据结构与算法中的经典算法
- Django-ftpserver 的两个坑
- 【VMware16的安装以及安装Linux教程(超详细上)
- 生命,因追逐梦想而精彩
- 【G4基础04】2.4 How to Specify Particles
- [单片机框架][DFU] Dfu升级例子 带crc校验+超时机制+led指示灯+芯片加锁+芯片自擦
- 超大背包问题(01背包)
- SF58-ASEMI快恢复二极管SF58的发展意义