- 论坛徽章:
- 0
|
这个是我从mini_snmpd修改过来的main函数。我的想法是通过select来判断是否有网络请求,然后再fork一个子进程去处理,但是waitpid会是父进程阻塞,这样的话如果我有几个客户端同时访问snmpd服务器,比没有用fork时候的响应还慢。用ps看也只有两个进程在运行,没有达到我想要的当访问的连接就fork多个进程的结果。
我也试过用下面这个函数来处理SIGCHLD来回收子进程,但是效果都还不如没有用多进程的响应快。
static void handle_child(int signo)
{
int status;
pid_t pid;
while(1)
{
pid = waitpid((pid_t) -1,&status,WNOHANG);
if((int) pid == 0)
break;
if ( (int) pid < 0 )
{
if ( errno == EINTR || errno == EAGAIN )
continue;
// ECHILD shouldn't happen with the WNOHANG option,
// but with some kernels it does anyway. Ignore it.
//
if ( errno != ECHILD )
{
syslog( LOG_ERR, "child wait - %m" );
perror( "child wait" );
}
break;
}
}
} |
int main(int argc, char *argv[])
{
struct sockaddr_in sockaddr;
socklen_t socklen;
fd_set rfds;
fd_set wfds;
int nfds;
int i;
int ret;
struct timeval tv;
oid_t oid;
pid_t pid;
int status;
/* Prevent TERM and HUP signals from interrupting system calls */
signal(SIGTERM, handle_signal);
signal(SIGHUP, handle_signal);
siginterrupt(SIGTERM, 0);
siginterrupt(SIGHUP, 0);
if(fork() > 0)
exit(0);
/* Open the server's UDP port and prepare it for listening */
g_udp_sockfd = socket(PF_INET, SOCK_DGRAM, 0);
if (g_udp_sockfd == -1) {
lprintf(LOG_ERR, "could not create UDP socket: %m\n");
exit(EXIT_SYSCALL);
}
sockaddr.sin_family = AF_INET;
sockaddr.sin_port = htons(g_udp_port);
sockaddr.sin_addr.s_addr = INADDR_ANY;
socklen = sizeof (sockaddr);
if (bind(g_udp_sockfd, (struct sockaddr *)&sockaddr, socklen) == -1) {
lprintf(LOG_ERR, "could not bind UDP socket to port %d: %m\n", g_udp_port);
exit(EXIT_SYSCALL);
}
/* Handle incoming connect requests and incoming data */
while (!g_quit) {
/* Sleep until we get data or a connection request */
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_SET(g_udp_sockfd, &rfds);
nfds = g_udp_sockfd;
tv.tv_sec = 0;
tv.tv_usec = 800000;
ret = select(nfds + 1, &rfds, &wfds, NULL, &tv);
if (ret == -1) {
if (g_quit) {
break;
}
// lprintf(LOG_ERR, "could not select from sockets: %m\n");
// exit(EXIT_SYSCALL);
}
else if(ret)
{
/* Handle UDP packets, TCP packets and TCP connection connects */
if (FD_ISSET(g_udp_sockfd, &rfds)) {
if( (pid = fork()) == 0)
{
handle_udp_client();
exit(0);
}
waitpid(pid,&status,0);
}
}
}
/* We were killed, print a message and exit */
lprintf(LOG_INFO, "mini_snmpd stopped\n");
return EXIT_OK;
} |
[ 本帖最后由 snakewind 于 2009-10-15 15:42 编辑 ] |
|