当SIGALRM时,select()返回套接字已准备就绪

时间:2013-07-08 12:02:01

标签: c linux select

如果这个问题已经响起,我很抱歉 - 找不到......所以 我有计时器:

bzero(&rtc_act, sizeof(struct sigaction));
rtc_act.sa_handler = &rtc_handler;
sigaction(SIGALRM, &rtc_act, NULL);

rtc_timer.it_interval.tv_sec = SETTIMER_INTERVAL;
rtc_timer.it_interval.tv_usec = 0;
rtc_timer.it_value.tv_sec = SETTIMER_VALUE;
rtc_timer.it_value.tv_usec = 0;

if (setitimer(ITIMER_REAL, &rtc_timer, NULL))
{
    printf(MSG_ERR_SETTIMER_FAIL);
    retval = RETURN_ERR_SETTIMER;
} /* if (setitimer(ITIMER_REAL, &rtc_timer, NULL)) */

我也阻止了套接字:

if ((modbus_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
    retval = RETURN_ERR_SOCKET_OPEN;
    perror(MSG_ERR_OPEN_SOCKET);
    return retval;
} /* if (modbus_socket = socket(AF_INET, SOCK_STREAM, 0) < 0) */

setsockopt(modbus_socket, SOL_SOCKET, SO_REUSEADDR, (const void*)&optval , sizeof(unsigned int));

bzero((char*)&serv_addr, sizeof(serv_addr));

serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons((unsigned short)ZK91_TCP_PORT_NUMBER);

if (bind(modbus_socket, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)
{
    perror(MSG_ERR_BIND_SOCKET);
    retval = RETURN_ERR_SOCKET_OPEN;
    return retval;
} /* if (bind(modbus_socket, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) */

if (listen(modbus_socket, TCP_CLIENTS_COUNT) < 0)
{
    perror(MSG_ERR_LISTEN_SOCKET);
    retval = RETURN_ERR_SOCKET_LISTEN;
    return retval;
} /* if (listen(parentfd, TCP_CLIENTS_COUNT) < 0) */

当我尝试使用select()

    FD_ZERO(&fds);
    FD_SET(modbus_socket, &fds);
    FD_SET(can_file, &fds);
    FD_SET(modbus_file, &fds);

    select(modbus_file + 1, &fds, NULL, NULL, &tv);

虽然实际数据不可用,但我会在几秒钟内获得激活select()。

如果您尝试处理此“连接”:

new_socket = accept(modbus_socket,(struct sockaddr *)&amp; client_addr,&amp; client_len);

然后程序崩溃,从那时为某个内存区域提供10个字符:

net即将到来(我的留言)

砗→

uclinux的#

如果我没有初始化计时器,那么一切正常,但在计时器上我无法拒绝。

可能是什么原因?

谢谢。

2 个答案:

答案 0 :(得分:1)

如果errno失败,您需要检查select()并忽略SIGALRM次中断。

类似的东西:

for (;;) {
    int rv = select(...);
    if (rv < 0) {
        if (errno == EINTR)
            continue;    // Was a signal
        else
            // A real error occurred
    } else {
        // Handle event
    }
}

答案 1 :(得分:0)

select()返回后,您必须检查 它返回的原因。你不能只是假设它正在说“套接字准备好阅读”而不进行检查。

使用FD_ISSET()宏完成检查,以查看套接字文件描述符是否仍在准备好读取集。

如果select()由于被中断而返回,则它还会将errno设置为EINTR,并返回-1。由于它通常返回三个输入集中的集合描述符的数量,因此您也应该检查返回值。除非FD_ISSET()返回的值大于0,否则无需开始调用select()