Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5799575
  • 博文数量: 409
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 8273
  • 用 户 组: 普通用户
  • 注册时间: 2013-10-23 19:15
个人简介

qq:78080458 学习交流群:150633458

文章分类

全部博文(409)

文章存档

2019年(127)

2018年(130)

2016年(20)

2015年(60)

2014年(41)

2013年(31)

分类: 嵌入式

2015-04-21 20:01:46

一、概念
1、线程可以安排它退出时的清理操作,这与进程的可以用atexit函数安排进程退出时需要调用的函数类似。这样的函数称为线程清理处理程序。线程
     可以建立多个清理处理程序,处理程序记录在栈中,所以这些处理程序执行的顺序与他们注册的顺序相反

pthread_cleanup_push(void (*rtn)(void*), void *args)//注册处理程序
pthread_cleanup_pop(int excute)//清除处理程序

2、当执行以下操作时调用清理函数,清理函数的参数由args传入
    1)、调用pthread_exit
    2)、响应取消请求
    3)、用非零参数调用pthread_cleanup_pop

3、清理函数的必要性
    也许你会认为线程不需什么清理操作,我可以在退出之前把所有该办的事情办了。但是,你不能确保你的线程永远正常的退出,加入它被取消呢。
    清理操作的优越性就在于,如果线程被取消了,那么清理函数会自动调用,这一点你是办不到的

4、清理函数要注意
    pthread_cleanup_push()  和 pthread_cleanup_pop()是用宏定义继承的,宏定义中包含{},因此他们两要成对出席那
    
二、手册
PTHREAD_CLEANUP_PUSH(3)    Linux Programmer’s Manual   PTHREAD_CLEANUP_PUSH(3)

NAME
       pthread_cleanup_push, pthread_cleanup_pop - push and pop thread cancellation clean-up handlers
        //注册或者销毁线程取消是的清理函数

SYNOPSIS
       #include
        //包含头文件pthread.h

       void pthread_cleanup_push(void (*routine)(void *),
                                 void *arg);
       void pthread_cleanup_pop(int execute);

       Compile and link with -pthread.
        //编译连接线程库

DESCRIPTION
       These functions manipulate the calling thread’s stack of thread-cancellation clean-up handlers.  A clean-up handler is a
       function that is automatically executed when a thread is canceled (or in various other circumstances  described  below);
       it might, for example, unlock a mutex so that it becomes available to other threads in the process.
        //这两个函数处理线程栈中的取消清理函数。一个清理函数会在线程被取消的时候执行,比如它可能去解锁一个互斥量
        //让它可以在其他线程中被使用

       The  pthread_cleanup_push()  function  pushes  routine  onto the top of the stack of clean-up handlers.  When routine is
       later invoked, it will be given arg as its argument.
        //pthread_cleanup_push()函数会将它的第一个参数指向的函数压入栈的顶端,当栈顶的函数被唤醒的时候,arg就是它的参数

       The pthread_cleanup_pop() function removes the routine at the top of the stack of clean-up handlers, and optionally exe-
       cutes it if execute is non-zero.
        //The pthread_cleanup_pop()函数将栈顶的清理函数从栈中清除,如果The pthread_cleanup_pop()的参数不是0 的话,清理
        //函数在被取出的时候还会执行


       A cancellation clean-up handler is popped from the stack and executed in the following circumstances:
        //一个取消清理操作会在一下的情况弹出并执行

       1. When  a  thread is canceled, all of the stacked clean-up handlers are popped and executed in the reverse of the order
          in which they were pushed onto the stack.
        //当线程被取消的时候,所有的被压入栈的清理函数都将弹出并执行,他们执行的顺序与入栈的顺序相反

       2. When a thread terminates by calling pthread_exit(3), all clean-up handlers are executed as described in the preceding
          point.  (Clean-up handlers are not called if the thread terminates by performing a return from the thread start func-
          tion.)
        //当一个线程用pthread_exit退出,所有的清理函数回像上面描述的一样执行。如果线程用return返回,那么清理函数不会
        //执行

       3. When a thread calls pthread_cleanup_pop() with a non-zero execute argument, the top-most clean-up handler  is  popped
          and executed.
        //如果线程以非零参数调用pthread_cleanup_pop(),栈顶的清理函数就会弹出执行

       POSIX.1  permits  pthread_cleanup_push()  and pthread_cleanup_pop() to be implemented as macros that expand to text con-
       taining '{' and '}', respectively.  For this reason, the caller must ensure that calls to  these  functions  are  paired within  the  same
       function,  and at the same lexical nesting level.  (In other words, a clean-up handler is only established during the execution of a
       specified section of code.)
        //在POSIX中, pthread_cleanup_push()  和 pthread_cleanup_pop()是用宏定义继承的,宏定义中包含{}。因此要确保这两个函数
        //是成对调用的


       Calling longjmp(3) (siglongjmp(3)) produces undefined results if any call has been  made  to  pthread_cleanup_push()  or
       pthread_cleanup_pop()  without  the  matching  call  of  the  pair  since  the  jump  buffer  was  filled  by  setjmp(3)
       (sigsetjmp(3)).  Likewise, calling longjmp(3) (siglongjmp(3)) from inside a clean-up handler produces undefined  results
       unless the jump buffer was also filled by setjmp(3) (sigsetjmp(3)) inside the handler.
        //在清理函数中调用longjmp或者siglongjmp都会产生未知的结果,除非他们和setjmp或者sigsetjmp成对的出现

RETURN VALUE
       These functions do not return a value.
        //这两个函数没有返回值

ERRORS
       There are no errors.
        //没有错误码

CONFORMING TO
       POSIX.1-2001.

NOTES
       On  Linux,  the pthread_cleanup_push() and pthread_cleanup_pop() functions are implemented as macros that expand to text
       containing '{' and '}', respectively.  This means that variables declared within the scope  of  paired  calls  to  these functions will
       only be visible within that scope.
        //在Linux中, pthread_cleanup_push()  and pthread_cleanup_pop()是用宏定义继承的,宏定义中包含{}。因此要确保这两个函数
        //是成对调用的

       POSIX.1  says  that  the  effect  of  using  return,  break,  continue,  or  goto to prematurely leave a block bracketed
       pthread_cleanup_push() and pthread_cleanup_pop() is undefined.  Portable applications should avoid doing this.

四、实例
return返回的线程不会执行清理操作,以非0参数调用pthread_cleanup_pop或者用pthread_exit退出的线程会执行清理操作

点击(此处)折叠或打开

  1. /*DATE:            2015-4-1
  2.  *AUTHOR:        WJ
  3.  *DESCRIPTION:    线程清理处理程序
  4.  *    pthread_cleanup_push(void (*rtn)(void*), void *args)//注册处理程序
  5.  *    pthread_cleanup_pop(int excute)//清除处理程序
  6.  *
  7.  *    这两个函数要成对的出现,否则编译无法通过
  8.  *
  9.  *    当执行以下操作时调用清理函数,清理函数的参数由args传入
  10.  *    1、调用pthread_exit
  11.  *    2、响应取消请求(请你来验证)
  12.  *    3、用非零参数调用pthread_cleanup_pop
  13.  */    

  14. #include "apue.h"

  15. void *fisrt_clean(void *arg)
  16. {
  17.     printf("%s fisrt clean\n", arg);
  18.     return(void *)0;
  19. }
  20. void *second_clean(void *arg)
  21. {
  22.     printf("%s second clean\n", arg);
  23.     return(void *)0;
  24. }

  25. void *thread_fun1(void *arg)
  26. {
  27.     printf("new thread 1\n");
  28.     pthread_cleanup_push(fisrt_clean, "thread1");
  29.     pthread_cleanup_push(second_clean, "thread1");

  30.     pthread_cleanup_pop(1);
  31.     pthread_cleanup_pop(0);

  32.     return(void *)1;
  33. }
  34. void *thread_fun2(void *arg)
  35. {
  36.     printf("new thread 2\n");
  37.     pthread_cleanup_push(fisrt_clean, "thread2");
  38.     pthread_cleanup_push(second_clean, "thread2");

  39.     pthread_exit((void *)2);
  40.     pthread_cleanup_pop(0);
  41.     pthread_cleanup_pop(0);

  42. }

  43. int main()
  44. {
  45.     pthread_t tid1, tid2;
  46.     int err;

  47.     err =pthread_create(&tid1, NULL, thread_fun1, NULL);
  48.     if(err != 0)
  49.     {
  50.         printf("create new thread 1failed\n");
  51.         return;
  52.     }
  53.     err =pthread_create(&tid2, NULL, thread_fun2, NULL);
  54.     if(err != 0)
  55.     {
  56.         printf("create new thread 2failed\n");
  57.         return;
  58.     }

  59.     sleep(2);

  60.     return 0 ;
  61. }
练习:当一个线程被取消,清理操作会执行

点击(此处)折叠或打开

  1. /*DATE:            2015-4-1
  2.  *AUTHOR:        WJ
  3.  *DESCRIPTION:    线程清理处理程序
  4.  *    pthread_cleanup_push(void (*rtn)(void*), void *args)//注册处理程序
  5.  *    pthread_cleanup_pop(int excute)//清除处理程序
  6.  *
  7.  *    这两个函数要成对的出现,否则编译无法通过
  8.  *
  9.  *    当执行以下操作时调用清理函数,清理函数的参数由args传入
  10.  *    1、调用pthread_exit
  11.  *    2、响应取消请求
  12.  *    3、用非零参数调用pthread_cleanup_pop
  13.  */    

  14. #include "apue.h"

  15. void *fisrt_clean(void *arg)
  16. {
  17.     printf("%s fisrt clean\n", arg);
  18.     return(void *)0;
  19. }
  20. void *second_clean(void *arg)
  21. {
  22.     printf("%s second clean\n", arg);
  23.     return(void *)0;
  24. }

  25. void *thread_fun1(void *arg)
  26. {
  27.     printf("new thread 1 start\n");
  28.     //设置清理函数
  29.     pthread_cleanup_push(fisrt_clean, "thread1");
  30.     pthread_cleanup_push(second_clean, "thread1");

  31.     //休眠2s,程序回到主线程,让主线程执行取消操作
  32.     sleep(2);

  33.     pthread_cleanup_pop(1);
  34.     pthread_cleanup_pop(0);

  35.     printf("new thread 1 over\n");
  36.     return(void *)1;
  37. }
  38. void *thread_fun2(void *arg)
  39. {
  40.     printf("new thread 2 start\n");
  41.     //设置清理函数
  42.     pthread_cleanup_push(fisrt_clean, "thread2");
  43.     pthread_cleanup_push(second_clean, "thread2");

  44.     //休眠2s,程序回到主线程,让主线程执行取消操作
  45.     sleep(2);

  46.     printf("new thread 2 over\n");
  47.     pthread_exit((void *)2);
  48.     pthread_cleanup_pop(0);
  49.     pthread_cleanup_pop(0);

  50. }

  51. int main()
  52. {
  53.     pthread_t tid1, tid2;
  54.     int err;

  55.     printf("main thread start\n");
  56.     //创造新线程
  57.     err =pthread_create(&tid1, NULL, thread_fun1, NULL);
  58.     if(err != 0)
  59.     {
  60.         printf("create new thread 1failed\n");
  61.         return;
  62.     }
  63.     err =pthread_create(&tid2, NULL, thread_fun2, NULL);
  64.     if(err != 0)
  65.     {
  66.         printf("create new thread 2failed\n");
  67.         return;
  68.     }

  69.     //休眠1s,让新线程设置清理函数
  70.     sleep(1);

  71.     //取消新线程
  72.     printf("main thread about to cancel new thread\n");
  73.     err = pthread_cancel(tid1);
  74.     if(err)
  75.         printf("cancel new thread 1 failed\n");
  76.     err = pthread_cancel(tid2);
  77.     if(err)
  78.         printf("cancel new thread 2 failed\n");

  79.     //等待新线程结束
  80.     printf("wait for new thread over\n");
  81.     pthread_join(tid1, NULL);
  82.     pthread_join(tid2, NULL);

  83.     printf("main thread over\n");

  84.     return 0 ;
  85. }





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