epoll_create 创建的 文件描述符和其他文件描述符一样,是被fork出的子进程继承的,那也就是子进程可以使用这个epoll fd添加感兴趣的io(epoll_ctl),然后是可以影响到父进程的epoll_wait。比如,子进程中注册了一个io写事件后,因为某种原因挂起来了,导致父进程的epoll_wait频繁返回,CPU占用率飙升。看下下面的演示代码:

    void DoWrite(int epollfd) {
  5     int fd = socket(AF_LOCAL, SOCK_STREAM, 0);
  6     if (fd < 0) {
  7         perror("socket ");
  8         exit(-1);
  9     }
10     struct sockaddr_un peer_addr;
11     memset(&peer_addr, 0, sizeof(peer_addr));
12     peer_addr.sun_family = AF_LOCAL;
13     const char *ipc_path =  "/home/longzhiri/my_code/nettest/localnettest.ipc";
14     strncpy(peer_addr.sun_path, ipc_path, sizeof(peer_addr.sun_path)-1);
15     if (connect(fd, (struct sockaddr *)&peer_addr,  SUN_LEN(&peer_addr))<0){
16         perror("connect ");
17         exit(-1);
18     }
19     struct epoll_event ev, events[10];
20     ev.events = EPOLLOUT;
21     ev.data.fd = fd;
22     if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) < 0) {
23         perror("epoll_ctl");
24         exit(-1);
25     }
26
27     sleep(10);
28     epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, &ev);
29     printf("child process exit\n");
30 }
31
32 int main(int argc, char *argv[]) {
33     int epollfd = epoll_create(10);
34     if (epollfd < 0) {
35         perror("epoll_create");
36         return -1;
37     }
38
39     struct epoll_event events[10];
40     int pid = fork();
41     if (pid < 0) {
42         perror("fork");
43         return -1;
44     } else if (pid > 0) {
45         for (;;) {
46             int nfds = epoll_wait(epollfd, events, 10, -1);
47             if (nfds < 0) {
48                 perror("epoll_wait 1");
49                 return -1;
50             }
51             printf("wake up +++\n");
52         }
53     } else {
54         DoWrite(epollfd);
55     }
56     return 0;
57 }
                               
真实环境看起来很难犯这种错误,但其实在使用第三方库的时候,因为隐藏不少逻辑,犯错的概率就高了。比如在使用libevent的时候,fork出的子进程想要复用父进程的event_base是必需调用event_reinit的,但是不了解这个问题的人就会直接拿父进程的event_base来使用。看下event_reinit的代码,底层使用了epoll的重新epoll_create出一个epollfd的,而不是重用父进程的,也就是没有调用event_reinit,注册的读写事件,其实都是在父进程中那个epoll_wait那里返回。

epoll在fork子进程中的问题的更多相关文章

  1. epoll在socket通信中的应用

    当服务器需要服务多个客户时,需要使用并发通信,实现并发通信有以下几种方法: 1.在服务器中fork子进程来为每个客户服务  具体可参考http://www.cnblogs.com/ggjucheng/ ...

  2. epoll与fork

    使用epoll时,如果在调用epoll_create之后,调用了fork创建子进程,那么父子进程虽然有各自epoll实例的副本,但是在内核中,它们引用的是同一个实例.子进程向自己的epoll实例添加. ...

  3. fork子进程

    title: fork子进程 data: 2019/3/21 20:24:39 toc: true --- 这里实在学习socket编程前的小知识点,用来创建多个服务端 学习文档 函数可以有两个返回值 ...

  4. [fork]Linux中的fork函数详解

    ---------------------------------------------------------------------------------------------------- ...

  5. localtime死锁——多线程下fork子进程

    近期測试我们自己改进的redis,发如今做rdb时,子进程会一直hang住.gdb attach上.堆栈例如以下: (gdb) bt #0 0x0000003f6d4f805e in __lll_lo ...

  6. 缺陷的背后(四)---多进程之for循环下fork子进程引发bug

    导语 业务模块为实现高并发时的更快的处理速度,经常会采用多进程的方式去处理业务.多进程模式下常见的三种bug:for循环下fork子进程导致产生无数孙子进程,僵尸进程,接口窜包.本章主要介绍第一种常见 ...

  7. 转:fork()子进程创建

    源地址:http://blog.chinaunix.net/uid-23037385-id-2565472.html fork()子进程创建 在 UNIX 系统中,用户创建一个新进程的唯一方法就是调用 ...

  8. fork子进程僵尸问题及解决方案

    额,原来用 c 写 cgi 的时候用过 fork .那时候 cgi 的生命很短,所以遇到的问题压根没出现过.这次也是更加深入的对 fork 机制进行了一下了解. 参考这里的文档:http://ju.o ...

  9. fork子进程之间传输信息的方法(包含子进程与子进程之间区分的问题的解决)

    今天看到一道题,要求是父进程fork出两个子进程,子进程1需要给子进程2发送一个数据,然后子进程2再将这个数据发送给父进程 具体思想如下. 父进程fork出来的子进程的pid,只有父进程保存下来了, ...

随机推荐

  1. 实验3 C语言分支语句和循环语句编程应用(友好猜日期^_^)

    实验任务一 #include <stdio.h> #include <math.h> int main(){ float a, b, c, x1, x2; float delt ...

  2. MybatisPlus学习(四)条件构造器Wrapper方法详解

    文章目录 1.条件构造器 2.QueryWrapper 2.1.eq.ne 2.2.gt.ge.lt.le 2.3.between.notBetween 2.4.like.notLike.likeLe ...

  3. Git设置记住账号密码

    Git设置记住账号密码 添加如下配置 [credential] helper = store

  4. Java虚拟机详解04----GC算法和种类

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  5. [leetcode]62.UniquePaths

    /** * Created by lvhao on 2017/7/6. * A robot is located at the top-left corner of a m x n grid (mar ...

  6. How to install android studio on ubuntu14.04

    First: open the web page: https://developer.android.com/studio/index.html download the Android Studi ...

  7. 浅谈java中的枚举类型(转)

    用法一:常量 在JDK1.5 之前,我们定义常量都是: public static fianl.... .现在好了,有了枚举,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法. p ...

  8. 对接口报错404 发现url多了一些不可描述的代码%E2%80%8B

    接口url出现了空格,复制的url可能出现空格肉眼看不出来,手动输入一遍URL

  9. Java 8 之前的时间处理

    最近在自己瞎折腾,有一个需求是计算当前日期到指定日期有多少天,用于实现纪念日或倒计时的功能.查阅资料后发现Java 8之前的时间日期处理很是麻烦而且被频频吐槽,以至于后来在 Java 8 中推出了一个 ...

  10. Mac使用HomeBrew

    前言 考虑许久终于决定入手mac耍耍,还是因为要找工作了,手上的win本大学入的,现在使用卡顿太多,另外就是mac作为程序员之友仰慕已久.决定在PDD入了.到手后发现mac真的跟win有很大差别.还是 ...