线程取消点的困惑

在一本书上看到这样一段关于线程取消点的描述: 线程取消的方法是向目标线程发Cancel信号,但如何处理Cancel信号则由目标线程自己决定,或者忽略、或者立即终止、或者继续运行至Cancelation-point(取消点),由不同的Cancelation状态决定。 线程接收到CANCEL信号的缺省处理(即pthread_create()创建线程的缺省状态)是继续运行至取消点,也就是说设置一个CANCELED状态,线程继续运行,只有运行至Cancelation-point的时候才会退出。 2.3 取消点 根据POSIX标准,pthread_join()、pthread_testcancel()、pthread_cond_wait()、 pthread_cond_timedwait()、sem_wait()、sigwait()等函数以及read()、write()等会引起阻塞的系统调用都是Cancelation-point,而其他pthread函数都不会引起Cancelation动作。但是pthread_cancel的手册页声称,由于LinuxThread库与C库结合得不好,因而目前C库函数都不是Cancelation-point;但CANCEL信号会使线程从阻塞的系统调用中退出,并置EINTR错误码,因此可以在需要作为Cancelation-point的系统调用前后调用 pthread_testcancel(),从而达到POSIX标准所要求的目标,即如下代码段: pthread_testcancel(); retcode = read(fd, buffer, length); pthread_testcancel(); 2.4 程序设计方面的考虑 如果线程处于无限循环中,且循环体内没有执行至取消点的必然路径,则线程无法由外部其他线程的取消请求而终止。因此在这样的循环体的必经路径上应该加入pthread_testcancel()调用。 2.5 与线程取消相关的pthread函数 int pthread_cancel(pthread_t thread) 发送终止信号给thread线程,如果成功则返回0,否则为非0值。发送成功并不意味着thread会终止。 int pthread_setcancelstate(int state, int *oldstate) 设置本线程对Cancel信号的反应,state有两种值:PTHREAD_CANCEL_ENABLE(缺省)和 PTHREAD_CANCEL_DISABLE,分别表示收到信号后设为CANCLED状态和忽略CANCEL信号继续运行;old_state如果不为 NULL则存入原来的Cancel状态以便恢复。 int pthread_setcanceltype(int type, int *oldtype) 设置本线程取消动作的执行时机,type由两种取值:PTHREAD_CANCEL_DEFFERED和 PTHREAD_CANCEL_ASYCHRONOUS,仅当Cancel状态为Enable时有效,分别表示收到信号后继续运行至下一个取消点再退出和立即执行取消动作(退出);oldtype如果不为NULL则存入运来的取消动作类型值。 void pthread_testcancel(void) 检查本线程是否处于Canceld状态,如果是,则进行取消动作,否则直接返回 按照以上的描述是不是说在linux下,pthread_join()、pthread_testcancel()、 pthread_cond_wait()、pthread_cond_timedwait()、sem_wait()、sigwait()等函数以及 read()、write()等会引起阻塞的系统调用在linux下并不是取消点啊?我不明白为什么可以在需要作为Cancelation-point的系统调用前后调用pthread_testcancel(),就可以达到POSIX标准所要求的目标,我还是不太理解取消点的内涵, pthread_testcancel(); retcode = read(fd, buffer, length); pthread_testcancel(); 加两个pthread_testcancel(); 是干什么的?特别是最后一个pthread_testcancel();按照上面的描述是不是线程运行到retcode = read(fd, buffer, length); 线程就终止了?那还要最后一个pthread_testcancel();做什么啊? ------------------------------ 昨天为了实现带超时的事件等待而查了些东西,偶然也看到了取消点,我来说说我的理解,如果有错误还请指出。 首先,取消点并不是为了取消而存在的(pthread_testcancel除外),它们是等待其他信号的,比如pthread_cond_wait是等待某个条件的,sem_wait等待一个信号量。它们的共同点是“引起阻塞的系统调用”,在阻塞以后,除了等待的特定信号以外还可以处理一些公共信号,比如CANCEL信号。接收到特定信号后将恢复线程,而接收到CANCEL信号将退出线程(我理解为一个条件return)。 Read和Write在POSIX中是标准的取消点,因为它们也进行了“引起阻塞的系统调用”,但是因为Linux自身的问题,没有在这些函数中实现取消点,所以才需要添加pthread_testcancel来完成POSIX标准。按照你贴出的文字,C库函数都没有实现取消点,其他的pthread_开头的和wait结尾的应该都是实现了的。 至于后面也加pthread_testcancel,可能是进入和退出系统调用是两个独立的取消点吧,应对于I/O操作开始后但还未结束时的CANSEL信号,也许只是因为I/O比较费时间所以测试两次:) ---------------------------------------

 

 

昨天为了实现带超时的事件等待而查了些东西,偶然也看到了取消点,我来说说我的理解,如果有错误还请指出。

首先,取消点并不是为了取消而存在的(pthread_testcancel除外),它们是等待其他信号的,比如pthread_cond_wait是等 待某个条件的,sem_wait等待一个信号量。它们的共同点是“引起阻塞的系统调用”,在阻塞以后,除了等待的特定信号以外还可以处理一些公共信号,比 如CANCEL信号。接收到特定信号后将恢复线程,而接收到CANCEL信号将退出线程(我理解为一个条件return)。
Read和Write在POSIX中是标准的取消点,因为它们也进行了“引起阻塞的系统调用”,但是因为Linux自身的问题,没有在这些函数中实现取消 点,所以才需要添加pthread_testcancel来完成POSIX标准。按照你贴出的文字,C库函数都没有实现取消点,其他的pthread_开 头的和wait结尾的应该都是实现了的。
至于后面也加pthread_testcancel,可能是进入和退出系统调用是两个独立的取消点吧,应对于I/O操作开始后但还未结束时的CANSEL信号,也许只是因为I/O比较费时间所以测试两次:)

 

 

 

 

 

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

 

 

谢谢楼上好心人的回答,不过我在我FC2下编个小程序尝试了一下,我觉得read接受到cancel信号后也会退出,下面是程序,我试了一下将注释1处的 read给注释掉程序将输出helloworld,如果保留的话,程序不会有任何输出,另外我发现如果sleep收到cancel信号线程也会退出,可以 将下面的程序稍微修改一下,就可以看到结果
#include   <stdio.h>
#include   <pthread.h>
#include   <sys/types.h>
#include   <unistd.h>
#include   <fcntl.h>
int   d=0;
int   fd;
char   buf[40];

void   *search(void   *arg)
{
 
  fd=open( "/home/myprj/thread1.c ",O_RDONLY);
  for(d=0;d <=99999999;d++);
  //pthread_testcancel();
  read(fd,buf,40);     /*注释1*/

  //sleep(1);
  //   pthread_testcancel();
    printf( "helloworld/n ");
}
int   main()
{
                                                                                                                                                                                                                                                         
  pthread_t   tid1;
  pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
  pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL);
  pthread_create(&tid1,NULL,search,NULL);
  pthread_cancel(tid1);
  pthread_join(tid1,NULL);
                                                                                                                                                                                                                      }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值