学科分类
目录
Linux编程

线程终止

在线程操作中有一个与终止进程的函数kill()对应的系统调用,即pthread_cancel(),使用该函数可以通过向指定线程发送CANCEL信号,使一个线程强行杀死另外一个线程。pthread_cancel()函数位于函数库pthread.h中,其声明如下:

int pthread_cancel(pthread_t thread);

pthread_cancel()中的参数thread为线程id,若函数调用成功则返回0,否则返回errno。使用pthread_cancel()函数终止的进程其退出值为PTHREAD_CANCELED,该宏定义在头文件pthread.h中,其值为-1。

与进程不同的是,调用pthread_cancel()函数杀死进程时,需要等待线程到达某个取消点,线程才会成功被终止。类似于单机游戏中只有到达城镇中的存档点时才能执行存档操作,在多线程编程中,只有到达取消点时系统才会检测是否有未响应的取消信号,并对信号进行处理。

所谓取消点即是线程执行过程中会检测是否有未响应取消信号的点,可粗略地认为只要有系统调用(进入内核)发生,就会进入取消点,如在程序中调用read()、write()、pause()等函数时都会出现取消点。取消点通常伴随阻塞出现,用户也可以在程序中通过调用pthread_testcancel()函数创造取消点。

下面通过一个案例来展示pthread_cancel()函数的用法。

案例4:在程序中使用pthread_cancel()函数,使主线程终止指定线程。

 1    #include <stdio.h>
 2    #include <unistd.h>
 3    #include <pthread.h>
 4    #include <stdlib.h>
 5    void *tfn(void *arg)
 6    {
 7        while (1) {
 8            printf("child thread...\n");
 9            pthread_testcancel();               //设置取消点
 10        }   
 11    }
 12    int main(void)
 13    {
 14        pthread_t tid;
 15        void *tret = NULL;
 16        pthread_create(&tid, NULL, tfn, NULL);
 17        sleep(1);
 18        pthread_cancel(tid);
 19        pthread_join(tid, &tret);
 20        printf("child thread exit code = %ld\n", (long int)tret);
 21        return 0;
 22    }

编译案例4,执行程序,执行结果如下:

child thread...
…
child thread...
child thread...child thread...
child thread exit code = -1

由执行结果可知,子线程在1秒后被主线程终止,子线程的退出码为-1,即PTHREAD_CANCELED。

pthread_exit()和pthread_cancel()都是线程机制中提供的用于终止线程的系统调用,pthread_exit()使线程主动退出,pthread_cancel()通过信号使线程被动退出。需要注意的是,由于在线程机制出现之前信号机制已经出现,信号机制在创建时并未将线程考虑在内,是以线程与信号机制的兼容性略有不足,因此在多线程编程中应尽量避免使用信号,以免出现难以调试的错误。

点击此处
隐藏目录