main.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. #include <errno.h>
  2. #include <pthread.h>
  3. #include <stdint.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <sys/epoll.h>
  7. #include <sys/eventfd.h>
  8. #include <unistd.h>
  9. #define MAX_EVENTS 10
  10. static int efd; // eventfd 描述符
  11. static int efd2; // eventfd 描述符
  12. // 工作线程:等待2秒后向 eventfd 写入事件通知
  13. void *worker_thread(void *arg) {
  14. uint64_t u = 1;
  15. printf("工作线程:等待2秒后发送事件通知...\n");
  16. sleep(2); // 模拟耗时任务
  17. printf("工作线程:发送事件通知...\n");
  18. if (write(efd, &u, sizeof(u)) != sizeof(u)) {
  19. perror("工作线程写入 eventfd 出错");
  20. exit(EXIT_FAILURE);
  21. }
  22. printf("工作线程:事件通知已发送\n");
  23. return NULL;
  24. }
  25. int main() {
  26. int epoll_fd;
  27. struct epoll_event ev, events[MAX_EVENTS];
  28. int nfds;
  29. pthread_t tid;
  30. // 创建 eventfd,对象初始计数为 0
  31. efd = eventfd(0, 0);
  32. if (efd == -1) {
  33. perror("创建 eventfd 失败");
  34. exit(EXIT_FAILURE);
  35. } else {
  36. printf("创建 eventfd 成功,描述符 = %d\n", efd);
  37. }
  38. efd2 = dup(efd); // 复制 eventfd 描述符
  39. if (efd2 == -1) {
  40. perror("复制 eventfd 失败");
  41. close(efd);
  42. exit(EXIT_FAILURE);
  43. } else {
  44. printf("复制 eventfd 成功,描述符 = %d\n", efd2);
  45. }
  46. // 创建 epoll 实例
  47. epoll_fd = epoll_create1(0);
  48. if (epoll_fd == -1) {
  49. perror("创建 epoll 实例失败");
  50. close(efd);
  51. exit(EXIT_FAILURE);
  52. }
  53. // 将 eventfd 添加到 epoll 监听队列,关注可读事件
  54. ev.events = EPOLLIN;
  55. ev.data.fd = efd;
  56. if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, efd, &ev) == -1) {
  57. perror("epoll_ctl 添加 eventfd 失败");
  58. close(efd);
  59. close(epoll_fd);
  60. exit(EXIT_FAILURE);
  61. }
  62. // 将复制的 eventfd 添加到 epoll 监听队列,关注可读事件
  63. ev.data.fd = efd2;
  64. if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, efd2, &ev) == -1) {
  65. perror("epoll_ctl 添加复制的 eventfd 失败");
  66. close(efd);
  67. close(efd2);
  68. close(epoll_fd);
  69. exit(EXIT_FAILURE);
  70. }
  71. // 创建工作线程,模拟事件发生
  72. if (pthread_create(&tid, NULL, worker_thread, NULL) != 0) {
  73. perror("创建工作线程失败");
  74. close(efd);
  75. close(efd2);
  76. close(epoll_fd);
  77. exit(EXIT_FAILURE);
  78. }
  79. printf("主线程:使用 epoll_wait 等待事件...\n");
  80. // 阻塞等待事件发生
  81. nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
  82. if (nfds == -1) {
  83. perror("epoll_wait 失败");
  84. exit(EXIT_FAILURE);
  85. } else {
  86. printf("主线程:epoll_wait 返回,事件数量 = %d\n", nfds);
  87. }
  88. // 处理就绪事件
  89. // for (int i = 0; i < nfds; i++) {
  90. // if (events[i].data.fd == efd || events[i].data.fd == efd2) {
  91. // uint64_t count;
  92. // int fd = events[i].data.fd;
  93. // printf("主线程:事件发生在 fd = %d\n", fd);
  94. // if (read(fd, &count, sizeof(count)) != sizeof(count)) {
  95. // perror("从 eventfd 读取失败");
  96. // exit(EXIT_FAILURE);
  97. // }
  98. // printf("主线程:接收到 eventfd 事件,计数值 = %lu\n", count);
  99. // }
  100. // }
  101. // 等待工作线程结束
  102. pthread_join(tid, NULL);
  103. int r = close(epoll_fd);
  104. if (r == -1) {
  105. perror("关闭 epoll 实例失败");
  106. exit(EXIT_FAILURE);
  107. } else {
  108. printf("关闭 epoll 实例成功\n");
  109. }
  110. close(efd);
  111. close(efd2); // 关闭复制的 eventfd 描述符
  112. printf("test_epoll ok\n");
  113. return 0;
  114. }