前言:
线程级的清理处理, 相当于进程级的atexit函数
1.触发清理程序的3个条件:
- 调用pthread_exit时.
- 响应取消请求时.
- 用非0的execute参数调用pthread_cleanup_pop时.
2.pthread_cleanup_push函数:
- 原型: void pthread_cleanup_push(void (*rtn)(void *), void *arg);
- 头文件: <pthread.h>
- 参数:
- rtn为清理函数的名字.
- arg为该清理函数的参数.
- 说明: 这是线程清理处理程序的注册函数.
3.pthread_cleanup_pop函数:
-
原型: void pthread_cleanup_pop(int execute);
-
头文件: <pthread.h>
-
参数: 如果为0, 清理函数不被调用.
//《APUE》程序11-4:线程清理处理程序
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void cleanup(void *arg)
{
printf("cleanup: %s\n", (char*)arg);
}
void *thr_fn1(void *arg)
{
printf("thread 1 start\n");
pthread_cleanup_push(cleanup, "thread 1 first handler");
pthread_cleanup_push(cleanup, "thread 1 second handler");
printf("thread 1 push complete\n");
if( arg )
return (void*)1;
pthread_cleanup_pop(0);
pthread_cleanup_pop(0);
return (void*)1;
}
void *thr_fn2(void *arg)
{
printf("thread 2 start\n");
pthread_cleanup_push(cleanup, "thread 2 first handler");
pthread_cleanup_push(cleanup, "thread 2 second handler");
printf("thread 2 push complete\n");
if( arg )
pthread_exit( (void*)2 );
pthread_cleanup_pop(0);
pthread_cleanup_pop(0);
pthread_exit( void*)2 );
}
int main(void)
{
pthread_t tid1, tid2;
void *tret;
pthread_create(&tid1, NULL, thr_fn1, (void*)1);
pthread_create(&tid2, NULL, thr_fn2, (void*)1);
pthread_join(tid1, &tret);
printf("thread 1 exit code\n", (int)tret);
pthread_join(tid2, &tret);
printf("thread 2 exit code\n", (int)tret);
return 0;
}
结果图:
注解:
- 1号线程并没有执行清理处理函数, 因为它是return终止退出的, 而不是用pthread_exit函数退出.(在环境编程这本书写到,如果线程是通过从它的启动例程中返回而终止的话,那么它的清理处理程序就不会被调用)
- 线程的清理处理函数执行顺序和注册顺序相反, 这和进程的atexit清理处理函数一致.
- 必须把pthread_cleanup_push的调用和pthread_cleanup_pop的调用匹配起来,否则程序通不过编译。