加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

是否有一种非阻塞方法来检查数据的速度比select()和poll()更快?

发布时间:2020-12-16 07:51:41 所属栏目:百科 来源:网络整理
导读:我有一个C程序尽可能快地使用sendto()方法从发送器到接收器使用recvfrom()方法接收数据.数据封装在第2层以太网帧中,应用程序将以太网帧直接写入线路(无TCP或UDP甚至IP).这是在x86_64 Linux上(开发机器只是库存Ubuntu 14.04).我无意移植到任何其他操作系统,应
我有一个C程序尽可能快地使用sendto()方法从发送器到接收器使用recvfrom()方法接收数据.数据封装在第2层以太网帧中,应用程序将以太网帧直接写入线路(无TCP或UDP甚至IP).这是在x86_64 Linux上(开发机器只是库存Ubuntu 14.04).我无意移植到任何其他操作系统,应用程序设计范围适用于Linux,因此其他操作系统无关紧要.

发件人:

while (true)
    {
        sendResult = sendto(sockFD,txBuffer,fSize+headersLength,(struct sockaddr*)&socket_address,sizeof socket_address);
    }

接收器:

while (true)
    {
        recvfrom(sockFD,rxBuffer,fSizeTotal,NULL,NULL);
    }

我希望发件人能够检查收到的数据包;如果接收方应用程序退出,它会将数据发送回发送方,说“我退出”,因此发送方将停止发送数据.我在发送器上使用poll()来检查接收到的消息,如下所示,但这显着降低了传输速度,从1Gbps(968Mbps)到大约10Mbps.我正在使用1Gbps网卡的两台PC之间使用交叉电缆进行测试.发送方计算发送的帧数和帧大小,接收方计算接收到的帧数和帧大小,因此要确认,应用程序实际上是以接近线速接收,我不只是看看NIC利用率或类似情况.

民意调查()方法:

int rv;
struct pollfd ufds[1];
ufds[0].fd = sockFD;
ufds[0].events = POLLIN


while (true)
{
    sendResult = sendto(sockFD,sizeof(socket_address));

    // wait for events on the sockets,1ms timeout
    rv = poll(ufds,1,1);

    if (rv > 0) {
        if (ufds[0].revents & POLLIN) {
            recvfrom(sockFD,NULL);
        }
    }

}

1毫秒是可以为poll()方法设置的最低超时.这就是我的传输程序只能以10Mbps传输的原因.虽然CPU使用率最低,但应用程序可以很容易地使1Gbps链路饱和,我之前提到的速度达到了968Mbps(顺便说一下,这并不意味着峰值,即持续吞吐量).

我删除了poll()调用,并使用下面的示例切换到select(),但同样,使用最小的延迟,我可以在这里传输应用程序只能获得175Mbps.不接近原来的968Mbps;

选择()方法:

fd_set readfds;
struct timeval tv;
int rv,n;

FD_ZERO(&readfds);
FD_SET(sockFD,&readfds);
n = sockFD + 1;


while (true)
{
    sendResult = sendto(sockFD,sizeof(socket_address));

    tv.tv_sec = 0;
    tv.tv_usec = 000001;
    rv = select(n,&readfds,&tv);
    if (rv > 0) {
        if (FD_ISSET(sockFD,&readfds)) {
            recvfrom(sockFD,NULL);
    }

}

对于今天的系统来说,这两种方法似乎都太慢了(对于上面的所有测试,我的cpu使用率约为2%).我希望尽快将这个应用程序移到一些10GigE机器上并开始测试,但我显然不能使用这两种方法中的任何一种.有没有更快的方法可以检查?

我虽然这些应该是非阻塞的,但是由于要求超时,它们会在某种程度上阻塞;我见过this thread,但这不是我要求的答案.有没有方法我可以在调用它的那个时刻简单地调用那些检查,等待读取数据,然后如果没有数据等待读取则立即返回?

作为一个副节点,我还没有读过recvfrom方法()来查看发布之前延迟的位置但是我确实尝试了以下因为它只需要30秒来更改代码,结果导致最坏的结果低于1Mbps;

发件人:

while (true)
    {
        // Continually send a frame then check for a frame,send a frame then check for a frame...
        sendResult = sendto(sockFD,sizeof(socket_address));
        recvfrom(sockFD,NULL);
    }

解决方法

在任何时间段内都不需要轮询或选择阻止.如果poll或select的超时参数设置为零,则两个调用都会立即返回i / o可用性的指示.这消除了接合计时器和随后的舍入.

注意,我不清楚为什么如果只监视一个文件描述符,这将比简单的非阻塞轮询读取快得多.我预计当多个FD在使用时,这种方法的任何好处都会开始产生,所以有趣的是你的测试发现了这一点.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读