公司项目测试的时候,发现运行一段时间后会出现cpu百分之百的情况。

    想着可能是哪里出现了死循环,于是打算用gdb跟一下,结果gdb居然无法attach到进程。。。。。。

 

    查了查去,原来有一个优先级为RT的实时线程出现了死循环,并且由于配置了CPU的亲和属性,使得进程只运行在第一个核上,此时gdb就无法attach了

    使用taskset现场修改进程的cpu亲和属性后,发现这个占cpu百分百的实时线程并没有出现一般的死循环,而是每次都在pthread_rwlock_wrlock这个函数中,

    而更诡异的是,只要修改了cpu亲和属性,就没有“死循环了”。。。。。。

 

    于是写了一段实验代码

  1. 1 #define _GNU_SOURCE
  2. 2 #include "stdio.h"
  3. 3 #include "stdlib.h"
  4. 4 #include "unistd.h"
  5. 5 #include "pthread.h"
  6. 6 #include <sched.h>
  7. 7
  8. 8 pthread_rwlock_t rwlock;
  9. 9
  10. 10 void* task1(void *arg)
  11. 11 {
  12. 12 pthread_setname_np(pthread_self(), "task1");
  13. 13
  14. 14 while(1)
  15. 15 {
  16. 16 printf("\r\n task1 lock \r\n");
  17. 17 pthread_rwlock_wrlock(&rwlock);
  18. 18
  19. 19 printf("\r\n task1 unlock \r\n");
  20. 20 pthread_rwlock_unlock(&rwlock);
  21. 21
  22. 22 usleep(10);
  23. 23 }
  24. 24 }
  25. 25
  26. 26 void* task2(void *arg)
  27. 27 {
  28. 28 struct sched_param sparam;
  29. 29
  30. 30 pthread_setname_np(pthread_self(), "task2");
  31. 31
  32. 32 /* 设置为最高优先级的实时任务 */
  33. 33 sparam.sched_priority = sched_get_priority_max(SCHED_RR);
  34. 34 pthread_setschedparam(pthread_self(), SCHED_RR, &sparam);
  35. 35
  36. 36 while(1)
  37. 37 {
  38. 38 printf("\r\n task2 lock \r\n");
  39. 39 pthread_rwlock_wrlock(&rwlock);
  40. 40
  41. 41 printf("\r\n task2 unlock \r\n");
  42. 42 pthread_rwlock_unlock(&rwlock);
  43. 43
  44. 44 usleep(10);
  45. 45 }
  46. 46 }
  47. 47
  48. 48 int main(int argc, char *argv[])
  49. 49 {
  50. 50 pthread_t t1, t2, t3;
  51. 51 cpu_set_t cpuset;
  52. 52
  53. 53 /* 设置cpu亲和属性,将进程绑定在第一个核上 */
  54. 54 CPU_ZERO(&cpuset);
  55. 55 CPU_SET(0, &cpuset);
  56. 56 sched_setaffinity(0, sizeof(cpuset), &cpuset);
  57. 57
  58. 58 pthread_rwlock_init(&rwlock, NULL);
  59. 59
  60. 60 pthread_create(&t2, NULL, task1, NULL);
  61. 61 sleep(3);
  62. 62 pthread_create(&t3, NULL, task2, NULL);
  63. 63
  64. 64 while (1)
  65. 65 sleep(10);
  66. 66
  67. 67 return 0;
  68. 68 }

 

运行结果,如下图

 

真的出现了CPU百分百的情况!!!

 

1. 读写锁的“拿锁”和“放锁”操作并不是一个完整的原子操作,而是有可能操作到一半被调度出去;

2. 此次实验结果显示,task1(非实时)在做unlock操作时,已经修改了一部分读写锁的属性,此时task2(实时)lock时,发现不需要再阻塞了,只需要自旋等待(死循环)task1将unlock操作做完;

    然而由于task1是实时任务,整个进程又只绑定到了第一个核上,task1无法得到调度,造成了task2的死循环。

 

版权声明:本文为tp1226原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/tp1226/p/13923402.html