gpt4 book ai didi

linux - select 函数可能会更新 linux 中的超时参数。为什么它是 'may update'?

转载 作者:太空宇宙 更新时间:2023-11-04 10:32:39 26 4
gpt4 key购买 nike

我的操作系统是 Centos 6.4。

对于 select,linux 程序员手册说:“select 可能会更新超时参数以指示还剩多少时间……”

我想知道为什么它是“可能”而不是“必须”?有系统版本还是内核版本?

我做一个测试。test_code01.cpp

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <pthread.h>

#define BUFSIZE 1024

struct timeval g_timeout;

int main(int argc, char* argv[])
{
int sock_clientfd, ret_recvsize, i;
struct sockaddr_in dest, mine;
char buffer[BUFSIZE + 1];

// create socket fd
if ((sock_clientfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("Socket");
exit(EXIT_FAILURE);
}

// init server address that client will connetct to.
bzero(&dest, sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_port = htons(9567);
if(argc != 2)
{
printf("Usage: %s <dest ip>\n", argv[0]);
printf("Usage: %s 127.0.0.1\n", argv[0]);
return -1;
}

printf("-----\n");

if (inet_aton(argv[1], (struct in_addr *) &dest.sin_addr.s_addr) == 0)
{
perror(argv[1]);
exit(1);
}

// connect to server
printf("will connect!\n");
if (connect(sock_clientfd, (struct sockaddr *) &dest, sizeof(dest)) != 0)
{
perror("Connect ");
exit(EXIT_FAILURE);
}

int ret_select = 0;
fd_set readfds;
FD_SET(sock_clientfd, &readfds);

g_timeout.tv_sec = 3;
g_timeout.tv_usec = 0;

while(1)
{
ret_select = select(sock_clientfd + 1, &readfds, NULL, NULL, &g_timeout);

// Becasue select can update timeout, we need to set value for timeout.
// g_timeout.tv_sec = 3;
// g_timeout.tv_usec = 0;

// Recover sock_clienfd state
FD_SET(sock_clientfd, &readfds);

if(ret_select == 0)
{
printf("select wait timeout.\n");
continue;
}

bzero(buffer, BUFSIZE + 1);
ret_recvsize = recv(sock_clientfd, buffer, BUFSIZE, 0);
if(ret_recvsize > 0)
{
printf("get %d message:%s", strlen(buffer), buffer);
ret_recvsize=0;
}
else
{
printf("no data from server\n");
}
}

// close sock_clientfd
close(sock_clientfd);

return 0;
}

我执行这个test_code01.cpp,结果select只有第一次等待3秒,我认为是select修改超时。所以我修改代码如下:

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <pthread.h>

#define BUFSIZE 1024

// in order to facilitate the ovservation data
// the timeout is set to global varible
struct timeval g_timeout;

void* thredproc_looktimeout(void*)
{
while(1)
{
printf("left time: %ds %dms\n", g_timeout.tv_sec, g_timeout.tv_usec);
}
}

int main(int argc, char* argv[])
{
int sock_clientfd, ret_recvsize, i;
struct sockaddr_in dest, mine;
char buffer[BUFSIZE + 1];

// create socket fd
if ((sock_clientfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("Socket");
exit(EXIT_FAILURE);
}

// init server address that client will connetct to.
bzero(&dest, sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_port = htons(9567);
if(argc != 2)
{
printf("Usage: %s <dest ip>\n", argv[0]);
printf("Usage: %s 127.0.0.1\n", argv[0]);
return -1;
}

printf("-----\n");

if (inet_aton(argv[1], (struct in_addr *) &dest.sin_addr.s_addr) == 0)
{
perror(argv[1]);
exit(1);
}

// connect to server
printf("will connect!\n");
if (connect(sock_clientfd, (struct sockaddr *) &dest, sizeof(dest)) != 0)
{
perror("Connect ");
exit(EXIT_FAILURE);
}

int ret_select = 0;
fd_set readfds;
FD_SET(sock_clientfd, &readfds);
printf("fdset add fd start+++\n");
for(int i = 0; i < 2000; i++)
{
FD_SET(1025+i, &readfds);
}
printf("%d--%s\n", errno, strerror(errno));
printf("fdset add 2000 fd finish...\n");

g_timeout.tv_sec = 3;
g_timeout.tv_usec = 0;


/**
* look timeout left time by create thread
**/
pthread_t tid;
int ret_pthreadcreate = pthread_create(&tid, NULL, thredproc_looktimeout, NULL);
printf("pthread_create return value is %d\n", ret_pthreadcreate);

while(1)
{
ret_select = select(sock_clientfd + 1, &readfds, NULL, NULL, &g_timeout);

// Becasue select can update timeout, we need to set value for timeout.
g_timeout.tv_sec = 3;
g_timeout.tv_usec = 0;

// Recover sock_clienfd state
FD_SET(sock_clientfd, &readfds);

if(ret_select == 0)
{
printf("select wait timeout.\n");
continue;
}

bzero(buffer, BUFSIZE + 1);
ret_recvsize = recv(sock_clientfd, buffer, BUFSIZE, 0);
if(ret_recvsize > 0)
{
printf("get %d message:%s", strlen(buffer), buffer);
ret_recvsize=0;
}
else
{
printf("no data from server\n");
}
}

// close sock_clientfd
close(sock_clientfd);

return 0;
}

我认为我们应该在 thredproc_looktimeout 中看到超时的变化。但没有变化。我不知道为什么?

最佳答案

手册页意味着返回超时可能会更新以指示剩余的时间量。这绝对不意味着在等待仍在进行时会更新超时。

即使是,您也无法检测到它。您尝试使用线程将无法工作,因为它没有任何类型的同步。除其他问题外,编译器可以优化 while 循环以仅读取一次 g_timeout。并且没有任何可以使用的同步机制。

关于linux - select 函数可能会更新 linux 中的超时参数。为什么它是 'may update'?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39113748/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com