- 论坛徽章:
- 0
|
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[1024+1] = {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[i].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);
}
}
} |
|