Chinaunix首页 | 论坛 | 博客
  • 博客访问: 78830
  • 博文数量: 8
  • 博客积分: 228
  • 博客等级: 二等列兵
  • 技术积分: 153
  • 用 户 组: 普通用户
  • 注册时间: 2012-06-04 22:00
文章分类
文章存档

2012年(8)

分类: LINUX

2012-10-11 10:37:11


点击(此处)折叠或打开

  1. #include
  2. void pthread_cleanup_push(void( *fn)(void*)),(void* arg))

  3. void pthread_cleanup_pop(int excute)
这 两个函数可以安排执行线程退出后需要执行的清理函数,这两个函数和进程退出时的atexit很像。

点击(此处)折叠或打开

  1. #include
  2. atexit(void(*fn)(void ));
“线程取消函数”即线程被取消或者下面描述的情况发生时自动调用的函数。它一般用于释放一些资源,比如释放锁,以免其它的线程永远 也不能获得锁,而造成死锁。
pthread_cleanup_push()函数执行压栈清理函数的操作,而pthread_cleanup_pop()函数执行从栈中删除清理函数的操作。
在下面三种情况下,pthread_cleanup_push()压栈的“清理函数”会被调用:
1, 线程调用pthread_exit()函数,而不是直接return.
2, 响应取消请求时,也就是有其它的线程对该线程调用pthread_cancel()函数。
3, 本线程调用pthread_cleanup_pop()函数,并且其参数非0

注意:
1.当pthread_cleanup_pop()函数的参数为0时,仅仅在线程调用pthread_exit函数或者其它线程对本线程调用 
     pthread_cancel函数时,才在弹出“清理函数”的同时执行该“清理函数”。
2.
注意pthread_exit终止线程与线程直接return终止线程的区别,调用return函数是不会在弹出“清理函数”的同时执行该“清理函数的。
3 .
pthread_cleanup_push()函数与pthread_cleanup_pop()函数必须成对的出现在同一个函数中
例子1.:
  1. include <pthread.h>
  2. #include <sys/types.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <unistd.h>
  6. #include <errno.h>

  7. #define handle_error_en(en, msg) \
  8. do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)

  9. static int done = 0;
  10. static int cleanup_pop_arg = 0;
  11. static int cnt = 0;

  12. static void cleanup_handler(void *arg)
  13. {
  14.         printf("Called clean-up handler\n");
  15.         cnt = 0;
  16. }

  17. static void *thread_start(void *arg)
  18. {
  19.         time_t start, curr;

  20.         printf("New thread started\n");
  21.         pthread_cleanup_push(cleanup_handler, NULL);
  22.         curr = start = time(NULL);
  23.         while(!done){
  24.                 pthread_testcancel(); /* A cancellation point */
  25.                 if(curr < time(NULL)){
  26.                         curr = time(NULL);
  27.                         printf("cnt = %d\n", cnt); /* A cancellation point */
  28.                         cnt++;
  29.                 }
  30.         }

  31.         pthread_cleanup_pop(cleanup_pop_arg);
  32.         return NULL;
  33. }

  34. int main(int argc, char *argv[])
  35. {
  36.         pthread_t thr;
  37.         void *res;

  38.         pthread_create(&thr, NULL, thread_start, NULL);
  39.         sleep(2); /* Allow new thread to run a while */

  40.         if(argc > 1){
  41.                 if(argc > 2)
  42.                         cleanup_pop_arg = atoi(argv[2]);
  43.                 done = 1;

  44.         }else{
  45.                 printf("Canceling thread\n");
  46.                 pthread_cancel(thr);
  47.         }

  48.         pthread_join(thr, &res);
  49.         if(res == PTHREAD_CANCELED)
  50.                 printf("Thread was canceled; cnt = %d\n", cnt);
  51.         else
  52.                 printf("Thread terminated normally; cnt = %d\n", cnt);
  53.         exit(EXIT_SUCCESS);
  54. }

点击(此处)折叠或打开

  1. #include
  2. #include
  3. #include
  4. #include
  5. void clean_fun1(void * arg)
  6. {
  7. printf("this is clean fun1\n");
  8. }
  9. void clean_fun2(void * arg)
  10. {
  11. printf("this is clean fun2\n");
  12. }
  13. void * thread_fun(void * arg)
  14. {
  15. pthread_cleanup_push(clean_fun1,NULL);
  16. pthread_cleanup_push(clean_fun2,NULL);
  17. sleep(100);
  18. //这里要注意,如果将sleep(100);换成while(1);的话,程序会一直暂停.push和pop要成对出现.
  19. //因为while(1);运行的太快,线程不接受cancel信号
  20. //while(1);
  21. pthread_cleanup_pop(0);
  22. pthread_cleanup_pop(0);
  23. return NULL;
  24. }
  25. int main()
  26. {
  27. pthread_t tid1;
  28. int err;
  29. err=pthread_create(&tid1,NULL,thread_fun,NULL);
  30. if(err!=0)
  31. {
  32. perror("pthread_create");
  33. exit(0);
  34. }
  35. sleep(3);
  36. //printf("test\n");
  37. err=pthread_cancel(tid1);
  38. if(err!=0)
  39. {
  40. perror("cancel error:");
  41. exit(0);
  42. }
  43. err=pthread_join(tid1,NULL);
  44. if(err!=0)
  45. {
  46. perror("pthread_join error:");
  47. exit(0);
  48. }

  49. return 0;
  50. }




















阅读(9857) | 评论(3) | 转发(0) |
给主人留下些什么吧!~~

hamasisn2014-11-13 11:12:19

请教个问题。
pthread_cleanup_push()把清理函数压入栈,如果是线程异常退出(pthread_exit,或是pthread_cancel),则调用清理函数。如果线程没有异常退出,则使用pthread_cleanup_pop把清理函数从栈中删除掉.
我的理解正确吗?

hamasisn2014-11-13 10:49:32

pthread_cleanup_push()函数执行把清理函数压入栈的操作,而pthread_cleanup_pop()函数执行从栈中删除清理函数的操作。

guoyuexiangying2014-05-15 17:00:46

文明上网,理性发言...