2013-07-08 3 views
0

미안 때 소켓이 준비 반환 - ... 찾을 수 없습니다 그래서 I이 타이머 :하는 소리가 이미 한이 질문은 경우 SIGALRM

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) */ 

내가 사용하려고하면 선택()

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); 

내가 몇 세코에서 선택 활성화()를 얻을 실제 데이터를 사용할 수는 없지만 nds.

이 "연결"을 처리하려고하면 :

new_socket = (modbus_socket (구조체 SOCKADDR의 *) & client_addr, & client_len)을 채택;

다음 프로그램은 화면을 다음에서 10 개 문자를주고 충돌은 몇 가지 메모리 영역 :

그물 (내 메시지)

硨의 L오고있다

uclinux #

타이머를 초기화하지 않으면 모든 것이 올바르게 작동하지만 타이머에서는 거부 할 수 없습니다.

왜 그럴 수 있습니까?

감사합니다.

+1

정말 어떤 소켓이 읽기 준비가되어 있음을 나타냅니다, 또는 그냥'의 errno = EINTR'를 사용하여 중단 된 것을 선택 하는가? –

+0

'modbus_file'은 정말 목록에서 가장 높은 fd입니까? 'printf ("modbus_socket % d can_file % d modbus_file % d \ n", ...);를 추가하여 어느 것이 가장 높은지 알 수 있습니까? –

+0

errno == EINTR. 그건 내 실수 였어. – user2214381

답변

0

select()이 반환 된 후 확인해야합니다. 이유가으로 반환됩니다. 확인하지 않고 "소켓 읽기 준비 완료"라고 가정 할 수는 없습니다.

FD_ISSET() 매크로를 사용하여 검사를 수행하면 소켓 파일 설명자가 아직 읽을 준비가되어 있는지 확인할 수 있습니다.

인터럽트로 인해 select()이 돌아 오는 경우 errnoEINTR으로 설정하고 -1을 반환합니다. 일반적으로 세 입력 집합에 설정된 설명자의 수를 반환하므로 반환 값도 확인해야합니다. select()가 값을 반환하지 않는 한 당신은 select()이 실패 할 경우 errno을 확인하고 SIGALRM 중단을 위해 그것을 무시 할 필요가 0보다 큰

1

보다 필요가 FD_ISSET()를 호출 시작 없습니다. 같은

뭔가 :

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

해당 코드가 [TEMP_FAILURE_RETRY] ​​(http://www.gnu.org/software/libc/manual/html_node/Interrupted-Primitives.html) 매크로와 동일하지 않습니까?나는 이식 할 수 없다는 것을 알고 있지만 질문은 리눅스로 태그가 붙어 있으므로 휴대용 솔루션이 절대적으로 필요하지는 않다. – simonc

+0

@imonc 그래, 나에게도 똑같아 보인다. 그러나 나는 그 매크로를 한번도 사용하지 않았기 때문에 그것에 대해 아무것도 모른다. 필자는 이처럼 복잡한 코드를 오히려 수작업으로 처리하고 싶습니다. – trojanfoe

+0

감사합니다. select() return에 관해서는 당신이 바로! 이 신호는 무시되지 않습니다. – user2214381