2014-03-26 2 views
0

vxworks 5.5.1의 posix socket api에 이상한 문제가 있습니다. 코드는 보통 이며 흥미로운 것은 아닙니다 (아래에 추가됨)이지만 그 요지는 다음과 같습니다. 을 호출하는 함수와 다른 함수로 socket()bind()을 호출하면 recvfrom() 호출에서 페이지 오류가 발생합니다. 모든 것이 동일한 기능으로 수행되면 정상적으로 작동합니다. 패킷이 도착하지 않을 때 recvfrom()을 호출하면 오류가 바로 발생합니다.VxWorks에서 recvfrom()을 사용할 때 Pagefault

VxWorks는이 API에 대해 예상치 못한 방식으로 스택을 사용합니까?

편집 : 일부 코드가 추가되었습니다. te_serve1() 함수는 정상적으로 작동하지만 te_serve_one() (도우미 함수 사용)은 작동하지 않습니다.

#include <taskLib.h> 
#include <sysLib.h> 
#include <string.h> 
#include <taskLib.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <types.h> 
#include <sys/socket.h> 
#include <sockLib.h> 
#include <netinet/in.h> 


#ifdef DEBUG 
#define DP(...) printf(__VA_ARGS__) 
#else 
#define DP(...) do { } while(0) 
#endif 

#define LLB(l, b) ((l & (0x000000FF << (b*8))) >> b*8) 


struct msg_log { 
    unsigned long src; 
    int   size; 
}; 

static int setup(short port) 
{ 
    int err = 0; 
    struct sockaddr_in addr; 
    int sock; 

    DP("socket()\n"); 
    err = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 
    if (err < 0) 
    return err; 
    sock = err; 

    addr.sin_family = AF_INET; 
    addr.sin_port = htons(7357); 
    addr.sin_addr.s_addr = htonl(INADDR_ANY); 

    DP("bind()\n"); 
    err = bind(sock, (struct sockaddr *)&addr, sizeof(addr)); 
    if (err) { 
    close(sock); 
    return err; 
    } 

    return sock; 
} 

static int serve(int sock, struct msg_log *log) 
{ 
    char buf[32]; 
    struct sockaddr_in caddr; 
    int caddr_len = sizeof(caddr); 
    int ret; 
    int len; 

    bzero((char *)&caddr, sizeof(caddr)); 
    DP("recvfrom()\n"); 
    ret = recvfrom(sock, buf, sizeof(buf), 0, 
     (struct sockaddr *) &caddr, &caddr_len); 
    if (ret < 0) return ret; 
    len = ret; 
    if (log) { 
    DP("log()"); 
    log->src = caddr.sin_addr.s_addr; 
    log->size = len; 
    } 
    DP("sendto()"); 
    ret = sendto(sock, (caddr_t) &buf, len, 0, (struct sockaddr *) &caddr, caddr_len); 

    return ret; 
} 

static void serve_multiple(int sock) 
{ 
    for (;;) 
    if (serve(sock, NULL) < 0) break; 
} 

int te_serve_one(void) 
{ 
    DP("%s\n", __FUNCTION__); 
    int sock; 
    struct msg_log log; /* = {0}; */ 
    int ret = 0; 
    short port = 1234; 

    DP("setup()\n"); 
    sock = setup(port); 
    if (sock < 0) 
    goto out; 
    sock = ret; 
    ret = serve(sock, &log); 
    if(ret < 0) 
    goto tidy; 

    DP("report:\n"); 
    printf("Echo'd %d byte to %lu.%lu.%lu.%lu\n", 
    log.size, 
    LLB(log.src, 0), 
    LLB(log.src, 1), 
    LLB(log.src, 2), 
    LLB(log.src, 3)); 

tidy: 
    DP("close()"); 
    close(sock); 
out: 
    return ret; 
} 

int te_serve1(short port) 
{ 
    int ret = 0; 
    int sock; 
    struct sockaddr_in addr; 
    char buf[32]; 
    struct sockaddr_in caddr; 
    int caddr_len = sizeof(caddr); 
    int len; 

    DP("socket()\n"); 
    ret = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); 
    if (ret < 0) 
    goto out; 
    sock = ret; 

    /* host addr */ 
    addr.sin_family = AF_INET; 
    addr.sin_port = htons(port); 
    addr.sin_addr.s_addr = htonl(INADDR_ANY); 

    DP("bind()\n"); 
    ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr)); 
    if (ret) 
    goto tidy; 

    /* serve */ 
    for (;;) { 
    DP("recvfrom()\n"); 
    ret = recvfrom(sock, buf, sizeof(buf), 0, 
      (struct sockaddr *) &caddr, &caddr_len); 
    if (ret < 0) 
     break; 
    len = ret; 

    if (len >= 4 && !strncmp(buf, "kill", 4)) { 
     ret = 0; 
     break; 
    } 

    DP("sendto()\n"); 
    ret = sendto(sock, (caddr_t) &buf, len, 0, 
     (struct sockaddr *) &caddr, caddr_len); 

    printf("Echo'd %d byte to %lu.%lu.%lu.%lu\n", 
     len, 
     LLB(caddr.sin_addr.s_addr, 0), LLB(caddr.sin_addr.s_addr, 1), 
     LLB(caddr.sin_addr.s_addr, 2), LLB(caddr.sin_addr.s_addr, 3)); 
    } 
tidy: 
    DP("close()"); 
    close(sock); 
out: 
    return ret; 
} 
+0

그렇지 않습니다. 아마도 당신은 recvfrom()에 잘못된 버퍼를 넘겨주고 있거나 스택 크기를 초과했을 수도 있습니다. 아마도 우리에게 몇 가지 코드를 보여줄 것입니다. – nos

+0

@nos : 질문에 코드가 추가되었습니다. – tommyo

답변

0

최적화 된 어셈블리를 살펴보면, sock 변수가 ret으로 덮어 쓰여지고 그 시점에서 사용되지 않고 0으로 초기화되었음을 알았습니다. 화려한.

0

settup()는 지역 다음 선언

구조체를 sockaddr_in 요지;

"struct sockaddr_in addr;"을 선언하면 어떻게됩니까? te_serve_one()에서 setup()에 전달 하시겠습니까?

+0

이것과 addr global을 사용하면 불행하게도 같은 결과를 얻을 수 있습니다. – tommyo