关于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()的运用,取消点的理解相关推荐

  1. 线程取消pthread_cancle、取消选项

    目录 pthread_cancel 杀死(取消)线程 取消选项 ① 可取消状态:PTHREAD_CANCLE_ENABLE.PTHREAD_CANCLE_DISABLE ②取消类型(推迟取消):PTH ...

  2. linux线程(互斥锁、条件)

    线程概念: 典型的UNIX/Linux进程可以看成只有一个控制线程:一个进程在同一时刻只做一件事情.有了多个控制线程后,在程序设计时可以把进程设计成在同一时刻做不止一件事,每个线程各自处理独立的任务. ...

  3. linux学习笔记 -- 系统编程

    系统编程 相关概念 概念 简易cpu结构 mmu内存管理单元 环境变量 PATH SHELL HOME LANG TERM getenv setenv unsetenv 进程控制 fork函数 get ...

  4. Linux多线程概念及实现

    目录 一.Linux线程基本概念 1.什么是线程 2.页表的映射 3.线程优点 4.线程缺点 5.线程异常 6.线程用途 二.Linux线程vs进程 1.线程和进程 2.进程的多个线程共享资源 3.进 ...

  5. Linux系统编程--守护进程、线程

    守护进程 Daemon(精灵)进程,是 Linux 中的后台服务进程,通常独立于控制终端并且周期性地执行某种任务或 等待处理某些发生的事件.一般采用以 d 结尾的名字. Linux 后台的一些系统服务 ...

  6. Linux(九)线程控制

    对于线程的操作接口(创建.终止.等待.分离) Linux下线程的操作接口,其实都是库函数,因为linux操作系统并没有直接向上层提供线程的系统调用接口,因此大佬们就基于系统调用接口封装实现了线程的相关 ...

  7. Linux tcpdump命令详解与Wireshark

    简介 用简单的话来定义tcpdump,就是:dump the traffic on a network,根据使用者的定义对网络上的数据包进行截获的包分析工具. tcpdump可以将网络中传送的数据包的 ...

  8. Linux 常用命令标记

    1.linux 服务器之间拷贝文件 scp 本地用户名@IP地址:文件名1 远程用户名@IP地址:文件名2 该命令可以变型为目的服务器204上输入如下命令:红色部分是需要接受目的地,-r是递归复制该文 ...

  9. tcpdump的简单选项介绍

    tcpdump采用命令行方式,它的命令格式为: tcpdump [ -AdDeflLnNOpqRStuUvxX ] [ -c count ] [ -C file_size ] [ -F file ] ...

  10. Linux tcpdump命令

    一.简介 用简单的话来定义tcpdump,就是:dump the traffic on a network,根据使用者的定义对网络上的数据包进行截获的包分析工具. tcpdump可以将网络中传送的数据 ...

最新文章

  1. 关于微服务的7个疑问和解答!
  2. 彻底给你讲清楚分布式事务原理
  3. AI Studio中的视觉数据集合
  4. win10+ubuntu双系统下,ubuntu不能访问windows的磁盘分区
  5. 算法与数据结构(python):递归
  6. 仿as3的displaylist
  7. OpenVINO 2019 R2.0 Custom Layer Implementation for linux(2)
  8. app传输数据到php,安卓app客户端和使用php的服务器端数据交互
  9. 金蝶移动bos开发教程_求助临沂金蝶k3,kis,eas软件各版本优势
  10. Downie 4 for Mac(视频下载)
  11. Android 滑动界面实现---Scroller类别 从源代码和开发文档了解(让你的移动布局)...
  12. NV21数据的镜像算法
  13. 数据结构与算法中的经典算法
  14. Django-ftpserver 的两个坑
  15. 【VMware16的安装以及安装Linux教程(超详细上)
  16. 生命,因追逐梦想而精彩
  17. 【G4基础04】2.4 How to Specify Particles
  18. [单片机框架][DFU] Dfu升级例子 带crc校验+超时机制+led指示灯+芯片加锁+芯片自擦
  19. 超大背包问题(01背包)
  20. SF58-ASEMI快恢复二极管SF58的发展意义

热门文章

  1. GHOST怎么用(转)
  2. 如何成为城建档案管理员(资料员)
  3. Gstreamer uridecodebin 插件手动选择解码器
  4. HTML代码 网页设置 QQ空间等分享
  5. SM2椭圆曲线公钥加密/解密算法
  6. 晓日程-首款打通微信和桌面的免费日历应用
  7. iPhone 各屏幕尺寸整理
  8. android内录音软件,安卓内录声音软件(能内录音频的手机软件)
  9. Android卡顿掉帧问题分析之实战篇
  10. 7723Java斗破苍穹_诛天-斗破苍穹(新)