hfree 发表于 2014-12-29 10:37

关于多线程,多进程epoll的惊群效应。

ubuntu@ubuntu:~/progs/src/hello$ uname -r
3.16.0-23-generic
ubuntu@ubuntu:~/progs/src/hello$ lsb_release -a
No LSB modules are available.
Distributor ID:Ubuntu
Description:Ubuntu 14.10
Release:14.10
Codename:utopic
ubuntu@ubuntu:~/progs/src/hello$


在以上环境发现,惊群效应并非每次都会出现,内核唤配epoll的进程应该是轮流来唤配的。当**第一个进程之后,如果这个进程的处理足够快,快到把多个进程同时监听的fd的事件都处理完了。那么其他的进程就不会被**了。

简单测试代码
while(true)
{
            //printf("%s epoll wait invoked...\r\n", szName);
           
            // 结论,多个进程同时epoll时,未必会引起惊群,猜测epoll有可读事件时,会轮着来**线程,
            // 同时每一个**的线程都会执行epoll_wait,如果前一个**的线程已经把epoll_wait里面的可读事件都处理完成了
            // 那么将不会再**剩下那些未**的线程。
      int ret = epoll_wait(epfd, events, 65535, -1);      
      
      // 加入这段sleep代码之后,所有创建的子进程都能在epoll中返回,并执行accept,但只有一个进程会accept成功。
      // 其余返回EAGAIN(11)
               // sleep(1);
              
      if(ret < 0)
      {
              char szError = {0};
              strerror_r(errno, szError, 1024);
            printf("%s epoll_wait error, errno:%d, err:%s\r\n", szName, (int)errno, szError);
                       
      }
      else if(ret == 0)
      {
              printf("%s get epoll event size: zero...\r\n", szName);
      }      

      for(int i = 0; i < ret; i++)
      {
            int sockfd = events.data.fd;
            if(sockfd == serverfd) //
            {
                struct sockaddr_in client_addr;
                socklen_t client_addrlen = sizeof(client_addr);

                int clientfd = accept(serverfd, (struct sockaddr*)&client_addr, &client_addrlen);
                       printf("%s accept client fd:%d\r\n", szName, clientfd);
            }
      }
}

gaojl0728 发表于 2014-12-30 11:31

**太多, 已经理解不了什么意思了。

yulihua49 发表于 2015-03-09 21:39

gaojl0728 发表于 2014-12-30 11:31 static/image/common/back.gif
**太多, 已经理解不了什么意思了。
唤 醒

现在是中国梦,不允许的动作。
页: [1]
查看完整版本: 关于多线程,多进程epoll的惊群效应。