千家信息网

unix 线程回调函数使用-pthread_cleanup_push && pthread_cleanup_pop

发表于:2025-01-23 作者:千家信息网编辑
千家信息网最后更新 2025年01月23日,#if 0线程结束时清理函数pthread_cleanup_push(),应该在线程开始的时候尽快执行初始化pthread_cleanup_pop(),当遇到以下三种各件会自动调用该函数,不需要PC执
千家信息网最后更新 2025年01月23日unix 线程回调函数使用-pthread_cleanup_push && pthread_cleanup_pop
  1. #if 0
  2. 线程结束时清理函数
  3. pthread_cleanup_push(),应该在线程开始的时候尽快执行初始化
  4. pthread_cleanup_pop(),当遇到以下三种各件会自动调用该函数,不需要PC执行到此函数
  5. 1.调用pthread_exit()
  6. 2.响应取消请求例如pthread_cancel()
  7. 3.当pthread_cleanup_pop(arg)参数arg为非0时会线程退出时自动执行
  8. 如果没有以上三种情况,则不会执行;
  9. #endif
  10. #include <pthread.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <unistd.h>
  14. #include <semaphore.h>
  15. sem_t sm0,sm1,sm2,sm3; //信号量定义 信号量为控制线程的执行
  16. void ret_fn(void*str)//线程退出调用的回调函数
  17. {
  18. fputs(str,stdout);
  19. }
  20. void thread0(void)
  21. {
  22. if(0 != sem_wait(&sm0))//信号量进行阻塞
  23. {
  24. perror("sem_wait_0");
  25. }
  26. char *str = "thead0_return_FN is runing\n";
  27. pthread_cleanup_push(ret_fn,str);//将回调函数入栈
  28. fputs("thread0 is runing\n",stdout);
  29. pthread_cleanup_pop(0);//将回调函数出栈,当遇到特定的条件会自动调用,不需要PC指到此才执行
  30. return;
  31. }
  32. void thread1(void)
  33. {
  34. if(0 != sem_wait(&sm1))
  35. {
  36. perror("sem_wait_1");
  37. }
  38. char *str = "thead1_return_FN is runing\n";
  39. pthread_cleanup_push(ret_fn,str);
  40. fputs("thread1 is runing\n",stdout);
  41. pthread_exit((void*)1);
  42. pthread_cleanup_pop(0);
  43. }
  44. void thread2(void)
  45. {
  46. if(0 != sem_wait(&sm2))
  47. {
  48. perror("sem_wait_2");
  49. }
  50. char *str = "thead2_return_FN is runing\n";
  51. pthread_cleanup_push(ret_fn,str);
  52. fputs("thread2 is runing\n",stdout);
  53. pthread_cleanup_pop(1);
  54. fputs("线程结束才会执行pthread_cleanup_pop\n",stdout);//线程结束才会执行pthread_cleanup_pop
  55. }
  56. void thread3(void)
  57. {
  58. char *str = "thead3_return_FN is runing\n";
  59. pthread_cleanup_push(ret_fn,str);
  60. if(0 != sem_wait(&sm3))
  61. {
  62. perror("sem_wait_3");
  63. }
  64. fputs("thread3 is runing\n",stdout);
  65. usleep(100);// 让主线程中的pthread_cancel可以执行
  66. pthread_cleanup_pop(0);
  67. }
  68. int main(void)
  69. {
  70. pthread_t thd0,thd1,thd2,thd3;
  71. if(0 != sem_init(&sm0,0,0))//初始化信号量
  72. {
  73. perror("sem_init_0");
  74. exit(1);
  75. }
  76. if(0 != sem_init(&sm1,0,0))
  77. {
  78. perror("sem_init_0");
  79. exit(1);
  80. }
  81. if(0 != sem_init(&sm2,0,0))
  82. {
  83. perror("sem_init_0");
  84. exit(1);
  85. }
  86. if(0 != sem_init(&sm3,0,0))
  87. {
  88. perror("sem_init_0");
  89. exit(1);
  90. }
  91. if(0 != pthread_create(&thd0,NULL,(void*)thread0,NULL))//创建线程
  92. {
  93. perror("pthread_create_0\n");
  94. exit(1);
  95. }
  96. if(0 != pthread_create(&thd1,NULL,(void*)thread1,NULL))
  97. {
  98. perror("pthread_create_1\n");
  99. exit(1);
  100. }
  101. if(0 != pthread_create(&thd2,NULL,(void*)thread2,NULL))
  102. {
  103. perror("pthread_create_2\n");
  104. exit(1);
  105. }
  106. if(0 != pthread_create(&thd3,NULL,(void*)thread3,NULL))
  107. {
  108. perror("pthread_create_3\n");
  109. exit(1);
  110. }
  111. unsigned char status = 0xF;//控制重复测试掩码
  112. while(1)
  113. {
  114. fputs("请输入测试选项:0(没有调用回调函数),1(pthread_exit),2(pthread_cancel),3(参数非0 pthread_cleanup_pop)\n",stdout);
  115. int in;
  116. scanf("%d",&in);
  117. switch(in)
  118. {
  119. case 0:
  120. {
  121. if(!(status & 0x1))
  122. {
  123. fputs("这个项目已测试过,请选择其它,谢谢\n",stdout);
  124. break;
  125. }
  126. if(0 != sem_post(&sm0))//激活信号量,让子线程THD0继续执行
  127. {
  128. perror("sem_post_0\n");
  129. }
  130. status &= 0xe;
  131. break;
  132. }
  133. case 1:
  134. {
  135. if(!(status & 0x2))
  136. {
  137. fputs("这个项目已测试过,请选择其它,谢谢\n",stdout);
  138. break;
  139. }
  140. if(0 != sem_post(&sm1))
  141. {
  142. perror("sem_post_1\n");
  143. }
  144. status &= 0xc;
  145. break;
  146. }
  147. case 2:
  148. {
  149. if(!(status & 0x4))
  150. {
  151. fputs("这个项目已测试过,请选择其它,谢谢\n",stdout);
  152. break;
  153. }
  154. if(0 != sem_post(&sm2))
  155. {
  156. perror("sem_post_2\n");
  157. }
  158. status &= 0xb;
  159. break;
  160. }
  161. case 3:
  162. {
  163. if(!(status & 0x8))
  164. {
  165. fputs("这个项目已测试过,请选择其它,谢谢\n",stdout);
  166. break;
  167. }
  168. if(0 != sem_post(&sm3))
  169. {
  170. perror("sem_post_3\n");
  171. }
  172. pthread_cancel(thd3);
  173. status &= 0x7;
  174. break;
  175. }
  176. default: break;
  177. }
  178. sleep(1);
  179. }
  180. return 0;
  181. }
0