linux高级编程之线程间的通信(pthread_cleanup_push和pthread_cleanup_pop)
2017-06-05 21:43
537 查看
linux高级编程之线程间的通信(pthread_cleanup_push和pthread_cleanup_pop)
线程可以安排他退出时需要调用的函数,这与进程可以用atexit函数安排进程退出时需要调用的函数是类似的。这样的函数称为线程清理处理程序,线程可以建立多个清理处理程序。处理程序记录在栈中,也就是说他们的执行顺序与他们注册的顺序相反。
pthread_cleanup_push和pthread_cleanup_pop函数原型如下:
头文件:#include <pthread.h>
函数原型:void pthread_cleanup_push(void (*rtn)(void *), void *arg);
void pthread_clean_pop(int execute);
void(*rtn)(void *): 线程清理函数
另外简单记录下pthread_cancel函数。该函数为线程取消函数,用来取消同一进程中的其他进程,函数原型:
头文件: #include <pthread.h>
函数原型:pthread_cancel(pthread_t tid);
tid: 线程id
当线程执行以下动作时,调用清理函数,调用的参数为arg,清理函数rtn的调用顺序是由pthread_cleanup_push函数来安排的。
●调用pthread_exit时
●响应取消请求时
●用非零execute参数调用pthread_cleanup_pop时
关于书上有句原话:“如果execute参数置为0,清理函数将不被调用”,我觉得说的有问题,而且接下来我摘抄了书上的一个例子,刚好验证了他说的这句话的错误,而且我也验证了下,当然在一篇博客中我看到这样的解释觉得很合理:当pthread_cleanup_pop()函数的参数为0时,仅仅在线程调用pthread_exit函数或者其它线程对本线程调用 pthread_cancel函数时,才在弹出“清理函数”的同时执行该“清理函数”。同样我也取了博客中的第二个例子来说明pthread_cancel调用时,pthread_cleanup_push会用清理函数。
参考博客:http://blog.chinaunix.net/uid-26772137-id-3369725.html
例1:
运行结果如下:
从输出结果可以看出:两个线程都调用了,但是却只调用了第二个线程的清理处理程序,所以如果线程是通过从它的启动历程中返回而终止的话,那么它的清理处理程序就不会被调用,还要注意清理程序是按照与它们安装时相反的顺序被调用的。从代码输出也可以看到先执行的thread 2 second handler后执行的thread 2 first handler。
例2:
运行结果如下:
从上面也可以看出,当调用pthread_cancel函数请求后,等到响应请求时,代码调用了pthread_clean_push函数中的clean_fun1和clean_fun2,函数clean_fun2中的语句先被打印。
线程可以安排他退出时需要调用的函数,这与进程可以用atexit函数安排进程退出时需要调用的函数是类似的。这样的函数称为线程清理处理程序,线程可以建立多个清理处理程序。处理程序记录在栈中,也就是说他们的执行顺序与他们注册的顺序相反。
pthread_cleanup_push和pthread_cleanup_pop函数原型如下:
头文件:#include <pthread.h>
函数原型:void pthread_cleanup_push(void (*rtn)(void *), void *arg);
void pthread_clean_pop(int execute);
void(*rtn)(void *): 线程清理函数
另外简单记录下pthread_cancel函数。该函数为线程取消函数,用来取消同一进程中的其他进程,函数原型:
头文件: #include <pthread.h>
函数原型:pthread_cancel(pthread_t tid);
tid: 线程id
当线程执行以下动作时,调用清理函数,调用的参数为arg,清理函数rtn的调用顺序是由pthread_cleanup_push函数来安排的。
●调用pthread_exit时
●响应取消请求时
●用非零execute参数调用pthread_cleanup_pop时
关于书上有句原话:“如果execute参数置为0,清理函数将不被调用”,我觉得说的有问题,而且接下来我摘抄了书上的一个例子,刚好验证了他说的这句话的错误,而且我也验证了下,当然在一篇博客中我看到这样的解释觉得很合理:当pthread_cleanup_pop()函数的参数为0时,仅仅在线程调用pthread_exit函数或者其它线程对本线程调用 pthread_cancel函数时,才在弹出“清理函数”的同时执行该“清理函数”。同样我也取了博客中的第二个例子来说明pthread_cancel调用时,pthread_cleanup_push会用清理函数。
参考博客:http://blog.chinaunix.net/uid-26772137-id-3369725.html
例1:
#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() { int err; pthread_t tid1,tid2; void *tret; err = pthread_create(&tid1,NULL,thr_fn1,(void *)1); if(err != 0) { fprintf(stderr,"thread create 1 is error\n"); return -1; } err = pthread_create(&tid2,NULL,thr_fn2,(void *)1); if(err != 0) { fprintf(stderr,"thread create 2 is error\n"); return -2; } err = pthread_join(tid1,&tret); if(err != 0) { fprintf(stderr,"can't join with thread 1\n"); return -2; } //pthread_cancel(tid1); printf("thread 1 exit code %d\n",tret); err = pthread_join(tid2,&tret); if(err != 0) { fprintf(stderr,"can't join with thread 2\n"); return -2; } printf("thread 2 exit code %d\n",tret); return 0; }
运行结果如下:
从输出结果可以看出:两个线程都调用了,但是却只调用了第二个线程的清理处理程序,所以如果线程是通过从它的启动历程中返回而终止的话,那么它的清理处理程序就不会被调用,还要注意清理程序是按照与它们安装时相反的顺序被调用的。从代码输出也可以看到先执行的thread 2 second handler后执行的thread 2 first handler。
例2:
#include<stdlib.h> #include<stdio.h> #include<unistd.h> #include<pthread.h> void clean_fun1(void * arg) { printf("this is clean fun1\n"); } void clean_fun2(void * arg) { printf("this is clean fun2\n"); } void * thread_fun(void * arg) { pthread_cleanup_push(clean_fun1,NULL); pthread_cleanup_push(clean_fun2,NULL); sleep(100); //这里要注意,如果将sleep(100);换成while(1);的话,程序会一直暂停.push和pop要成对出现. //因为while(1);运行的太快,线程不接受cancel信号 //while(1); pthread_cleanup_pop(0); pthread_cleanup_pop(0); return NULL; } int main() { pthread_t tid1; int err; err=pthread_create(&tid1,NULL,thread_fun,NULL); if(err!=0) { perror("pthread_create"); exit(0); } sleep(3); //printf("test\n"); err=pthread_cancel(tid1); if(err!=0) { perror("cancel error:"); exit(0); } err=pthread_join(tid1,NULL); if(err!=0) { perror("pthread_join error:"); exit(0); } return 0; }
运行结果如下:
从上面也可以看出,当调用pthread_cancel函数请求后,等到响应请求时,代码调用了pthread_clean_push函数中的clean_fun1和clean_fun2,函数clean_fun2中的语句先被打印。
相关文章推荐
- Linux pthread编程之cleaupn_push与cleanup_pop
- Linux--多线程之线程资源回收pthread_cleanup_push和pthread_cleanup_pop
- linux线程,pthread_join和pthread_cleanup_push和pthread_cleanup_pop
- linux高级编程基础系列:线程间通信
- linux高级编程基础系列:线程间通信
- linux高级编程基础系列:线程间通信
- 线程的终止方式:pthread_cleanup_push, pthread_cleanup_pop()
- linux高级编程基础系列:线程间通信
- linux高级编程基础系列:线程间通信
- linux高级编程基础系列:线程间通信
- 线程清理处理函数 pthread_cleanup_push、pthread_cleanup_pop
- 线程退出处理函数 pthread_cleanup_push pthread_cleanup_pop
- linux高级编程基础系列:线程间通信
- pthread_cleanup_push()/pop()线程终止清理
- IPC 简单的读写通信实例 linux环境高级编程
- test pthread_cleanup_push、pthread_cleanup_pop and pthread_exit
- pthread_cleanup_push() pthread_cleanup_pop()
- pthread_cleanup_push与pthread_cleanup_pop的目的(作用)
- pthread_cleanup_push() pthread_cleanup_pop()
- 【Linux的高级应用编程】进程间的通信机制