1 pthread_cancel函数
int pthread_cancel(pthread_t thread);
/*
功能:杀死(取消)线程,其作用,对应进程中kill()函数。
成功:0;失败:错误号。
参1:要杀死线程的tid。
*/
2 pthread_cancel函数案例
2.1 案例1
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
void *tfn(void *arg){
while(1){
printf("thread pid=%d, tid=%lu\n", getpid(), pthread_self());
sleep(1);
)
return NULL;
}
int main(int argc, char *argv[]){
pthread_t tid;
tid[i] = -1;
int ret = pthread_create(&tid[i], NULL, tfn, NULL);
if(ret != 0){
fprintf(stderr, "pthread_create failed:%s\n", strerror(ret));
exit(1);
}
printf("main pid=%d, tid=%lu\n", getpid(), pthread_self());
sleep(5);
pthread_cancel(tid);//终止线程,但需要一个执行的CPU分片
if(ret != 0){
fprintf(stderr, "pthread_create failed:%s\n", strerror(ret));
exit(1);
}
while(1);
return 0;
}
上面代码结果,当我们每一秒在子线程打印,5秒后主线程调用cancel函数成功杀死子线程。
2.2 案例2
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
void *tfn1(void *arg)
{
printf("thread 1 returning\n");
return (void *)111;
}
void *tfn2(void *arg)
{
printf("thread 2 exiting\n");
pthread_exit((void *)222);
}
void *tfn3(void *arg)
{
while (1) {
//printf("thread 3: I'm going to die in 3 seconds ...\n");
//sleep(1);
//pthread_testcancel(); //自己添加取消点*/
}
return (void *)666;
}
int main(void)
{
pthread_t tid;
void *tret = NULL;
pthread_create(&tid, NULL, tfn1, NULL);
pthread_join(tid, &tret);
printf("thread 1 exit code = %d\n\n", (int)tret);
pthread_create(&tid, NULL, tfn2, NULL);
pthread_join(tid, &tret);
printf("thread 2 exit code = %d\n\n", (int)tret);
pthread_create(&tid, NULL, tfn3, NULL);
sleep(3);
pthread_cancel(tid);
pthread_join(tid, &tret);
printf("thread 3 exit code = %d\n", (int)tret);
return 0;
}
结果分析,上面代码是第三个线程在主线程结束后将被杀死,但是图中并未杀死打印出:thread 3 exit codexxx,而是子线程继续卡死执行while(1)循环。这是为什么呢?这是因为调用pthread_cancel杀死子线程必须有系统调用函数,例如添加sleep()或者其它,注意if,switch这些不是系统调用,所以也不会给契机pthread_cancel杀死子线程。最好的方法是调用pthread_testcancel,它内部作了系统调用的处理。
3 总结pthread_cancel
- 1)pthread_cancel可以杀死子线程,但必须需要一个契机,这个契机就是系统调用。一般方法是调用pthread_testcancel提供契机处理。并且join再回收该被杀死的子线程的返回值为pthread.h中的宏#define PTHREAD_CANCELED ((void *) -1)。