3

我有一个接收 UDP 数据包(不发送)的 GTKmm Windows 应用程序(使用 MinGW 构建)。套接字是原生的 winsock,我使用 glibmm IOChannel 将其连接到应用程序主循环。使用 recvfrom 读取套接字。

我的问题是:这个设置在 3GHz 工作站上占用了 25% 的 CPU 时间。有人可以告诉我为什么吗?

在这种情况下,应用程序处于空闲状态,如果我删除 UDP 代码,CPU 使用率会下降到几乎为零。由于应用程序必须执行一些 CPU 密集型任务,我可以想象更好的方式来花费这 25%

以下是一些代码摘录:(对不起 printf 的;))


/* bind */
void UDPInterface::bindToPort(unsigned short port)
{
    struct sockaddr_in target;
    WSADATA wsaData;

    target.sin_family = AF_INET;
    target.sin_port = htons(port);
    target.sin_addr.s_addr = 0;

    if ( WSAStartup ( 0x0202, &wsaData ) )
    {
        printf("WSAStartup failed!\n");
        exit(0); // :)
        WSACleanup();
    }

    sock = socket( AF_INET, SOCK_DGRAM, 0 );
    if (sock == INVALID_SOCKET)
    {
        printf("invalid socket!\n");
        exit(0);
    }

    if (bind(sock,(struct sockaddr*) &target, sizeof(struct sockaddr_in) ) == SOCKET_ERROR)
    {
        printf("failed to bind to port!\n");
        exit(0);
    }

    printf("[UDPInterface::bindToPort] listening on port %i\n", port);
}

/* read */
bool UDPInterface::UDPEvent(Glib::IOCondition io_condition)
{
    recvfrom(sock, (char*)buf, BUF_SIZE*4, 0, NULL, NULL);
    /* process packet... */
}

/* glibmm connect */
Glib::RefPtr channel = Glib::IOChannel::create_from_win32_socket(udp.sock);
Glib::signal_io().connect( sigc::mem_fun(udp, &UDPInterface::UDPEvent), channel, Glib::IO_IN );

我在其他一些问题中以及在 glib 文档 (g_io_channel_win32_new_socket()) 中读到了套接字被置于非阻塞模式,这是“实现的副作用并且不可避免”。这是否解释了 CPU 效应,我不清楚?

我是否使用 glib 访问套接字或直接调用 recvfrom() 似乎没有太大区别,因为 CPU 在任何数据包到达之前就用完了并且读取处理程序被调用。glibmm 文档还指出,即使轮询套接字也可以调用 recvfrom() (Glib::IOChannel::create_from_win32_socket())

我尝试使用 -pg 编译程序并使用 gprof 创建每个函数的 cpu 使用情况报告。这没有用,因为时间没有花在我的程序上,而是花在了一些外部 glib/glibmm dll 上。

4

0 回答 0