문제

프로젝트의 경우 Linux 커널 공간에서 UDP 패킷을 보내려고합니다. 나는 현재 내 코드를 커널에 '하드 코딩'하고 있지만 (가장 좋은/가장 좋은 방법은 아니지만) 간단한 테스트를 받으려고 노력하고 있습니다 ( "테스트"보내기). 내가 커널 해킹에 대한 초보자라고 언급해야합니다. 나는 많은 원칙과 기술에 맞지 않습니다!

내 코드가 실행될 때마다 시스템이 매달려 있고 재부팅해야합니다. 마우스/키보드 응답이없고 스크롤 및 캡 잠금 키 조명이 함께 플래시가 깜박입니다. 이것이 무엇을 의미하는지 잘 모르겠지만 커널 공황이라고 가정하고 있습니까?

이 테스트 코드는 반복 _send 코드가 불필요하지만 작동 할 때 여러 '보내기가 필요한 큰 메시지를 보내고 싶습니다. 문제의 원인이 될 수 있는지 확실하지 않습니까?

NB이 코드는 Linux-Source/Net/Core/Origin의 Neighbour.c에 삽입되고 있으므로 Neight_printk1을 사용하면 매크로 래퍼 라운드 프린트크입니다.

나는 여기서 벽돌 벽에 머리를 두드리고있다. 나는 명백한 것을 발견 할 수 없다. 누구든지 나를 올바른 방향으로 가리킬 수 있습니까 (아니면 맹목적으로 명백한 오류가 있습니다!)?

지금까지 내가 가지고있는 것은 다음과 같습니다.

void mymethod()
{
    struct socket sock;
    struct sockaddr_in addr_in;
    int ret_val;
    unsigned short port = htons(2048);
    unsigned int host = in_aton("192.168.1.254");
    unsigned int length = 5;
    char *buf = "TEST\0";
    struct msghdr msg;
    struct iovec iov;
    int len = 0, written = 0, left = length;
    mm_segment_t oldmm;

    NEIGH_PRINTK1("forwarding sk_buff at: %p.\n", skb);

    if ((ret_val = sock_create(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock)) < 0) {
        NEIGH_PRINTK1("Error during creation of socket; terminating. code: %d\n", ret_val);
        return;
    }

    memset(&addr_in, 0, sizeof(struct sockaddr_in));
    addr_in.sin_family=AF_INET;
    addr_in.sin_port = port;
    addr_in.sin_addr.s_addr = host;

    if((ret_val = sock.ops->bind(&sock, (struct sockaddr *)&addr_in, sizeof(struct sockaddr_in))) < 0) {
    NEIGH_PRINTK1("Error trying to bind socket. code: %d\n", ret_val);
    goto close;
    }

    memset(&msg, 0, sizeof(struct msghdr));
    msg.msg_flags = 0;
    msg.msg_name = &addr_in;
    msg.msg_namelen = sizeof(struct sockaddr_in);
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;
    msg.msg_control = NULL;
    msg.msg_controllen = 0;

repeat_send:
    msg.msg_iov->iov_len = left;
    msg.msg_iov->iov_base = (char *)buf + written;

    oldmm = get_fs(); 
    set_fs(KERNEL_DS);
    len = sock_sendmsg(&sock, &msg, left);
    set_fs(oldmm);

    if (len == -ERESTARTSYS)
        goto repeat_send;
    if (len > 0) {
        written += len;
        left -= len;
        if (left)
            goto repeat_send;
    }

close:
    sock_release(&sock);
}

도움을 주셔서 감사합니다. 감사합니다!

도움이 되었습니까?

해결책

사용하기가 더 쉽다는 것을 알 수 있습니다 NetPoll API UDP 용. 보세요 netconsole 그것이 어떻게 사용되는지에 대한 예를 들어. 사용중인 API는 사용자 공간을 위해 더 의도 된 것입니다 (네트워크 데이터를 보내기 위해 세그먼트 디스크립터와 함께 플레이 할 필요가 없습니다!)

다른 팁

텍스트 모드 콘솔에있을 때 코드를 실행하십시오 (예 : 텍스트 콘솔로 이동하려면 Ctrl+Alt+F1을 누르십시오). 이런 식으로 커널 공황은 스택 추적과 무엇이 잘못되었는지에 대한 추가 정보를 인쇄합니다.

그렇지 않으면 도움이되지 않으면 스택 추적으로 질문을 업데이트하십시오.

나는 Linux 커널 개발자가 많지 않지만 인쇄물을 던져 DMESG가 내려 가기 전에 DMESG를 볼 수 있습니까? 아니면 커널 디버거와 연결에 대해 생각해 보셨습니까?

모든 변수를 MyMethod () 함수 외부에 넣고 정적으로 만들어야한다고 생각합니다. 커널 스택의 크기는 8kib가 제한되어 있으므로 너무 큰 로컬 변수로 인해 스택 오버플로 및 시스템 끊기가 발생할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top