低CPU使用率的方式来监控与本地主机的连接

时间:2019-04-04 04:52:41

标签: sockets cpu-usage connect nonblocking

似乎到本地主机的无阻塞连接总是立即失败,然后poll()立即返回,并且在revents中设置了POLLIN标志。这样可以防止CPU进入阻塞状态,并使整个系统以很高的CPU使用率运行。

PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
1470 panruoc+  20   0   12956   1956   1820 S  26.2  0.0   2:09.49 zz1

任何建议都适用。 这是我的测试代码

int main(int argc, char *argv[])
{
    struct sockdesc {
        char *host;
        int port;
        int sockfd;
    };
    struct sockdesc sdes[] = {
        {"localhost", 6000},
        {"111.206.239.212", 6000},
    };
    unsigned int i;

    for(i = 0; i < 2; i++) {
        tcp_connect(sdes[i].host, sdes[i].port, &sdes[i].sockfd);
        printf("sockfd = %d, %d\n", sdes[i].sockfd, errno);
    }

    if(!nonblocking)
        return 0;

    struct pollfd pollfds[2];
    pollfds[0].fd = sdes[0].sockfd;
    pollfds[1].fd = sdes[1].sockfd;
    pollfds[0].events = POLLIN;
    pollfds[1].events = POLLIN;

    int conns;
    for(conns = 0; conns != 3; ) {
        int nfds = poll(pollfds, 2, -1);
        if(nfds <= 0)
            exit(1);
        for(i = 0; (int)i < nfds; i++) {
            if(pollfds[i].revents) {
                if(pollfds[i].revents & POLLIN)
                    conns |= i;
                printf(" fd = %d, revents = 0x%04x\n", sdes[i].sockfd, pollfds[i].revents);
            }
        }
    }
    return 0;
}

BR,若晨

1 个答案:

答案 0 :(得分:0)

您的for循环看起来可疑:

for(conns = 0; conns != 3; ) {

conns什么时候变成三?

您的意图似乎在这里:

            if(pollfds[i].revents & POLLIN)
                conns |= i;

但是如果第一个套接字的i0,则conns |= i不会更改该值。

当两个套接字都有可用数据时,您的poll调用将立即开始返回,但是您陷入了无限循环。因此,CPU开销很高。

您的代码似乎打算一直处于循环状态,直到两个套接字都有可读取的数据为止。然后打破循环。所以我怀疑你真的是这个意思:

                conns |= (i+1);

还有其他问题。 poll返回有效套接字描述符的数量。因此这行;

for(i = 0; (int)i < nfds; i++) {

因此,如果与pollfds [1]关联的套接字具有可用数据,则nfds仅为1。因此,您的循环将仅评估pollfds[0]是否具有数据。

让我们清理代码:

int ready_set = 0x00;
int all_ready_set = 0x03;
int num_sockets = 2;
while (ready_set != all_ready_set)
{
    int nfds = poll(pollfds, 2, -1);

    if(nfds <= 0)
    {
        // I would not actually exit. If a socket gets closed locally, you would have a valid and expected error, but maybe that can't happen in your program
        exit(1);
    }

    for (i = 0; i < num_sockets; i++)
    {
        if (pollfds[i].revents & POLLIN)
        {
            int mask = 0x01 << i;
            pollfds[i].events = 0; // stop listening for events on this socket
            ready_set |= mask;
        }
    }
}