2009-11-29 77 views
0

對於一個項目,我試圖從Linux內核空間發送UDP數據包。我目前正在將我的代碼「硬編碼」到內核中(我不理解它是最好的/最新的方式),但我試圖讓一個簡單的測試工作(發送「TEST」)。應該指出,我是內核黑客的新手 - 我不是那種在許多原理和技術上找到的東西!在Linux內核中發送UDP數據包

每當我的代碼運行系統掛起,我必須重新啓動 - 沒有鼠標/鍵盤響應和滾動和大寫鎖定鍵燈閃爍在一起 - 我不知道這是什麼意思,但我假設它是內核恐慌?

repeat_send代碼對於此測試代碼是不必要的,但是當它工作時,我想發送可能需要多個'send'的大消息 - 我不確定如果可能是我的問題的原因?

N.B.這段代碼被插入到linux-source/net/core/origin的neighbour.c中,因此使用了NEIGH_PRINTK1,它只是一個宏包裝printk。

我真的把我的頭撞在這裏的磚牆上,我找不到任何明顯的東西,任何人都可以指向正確的方向(或者發現那個盲目的明顯錯誤!)?

這是我到目前爲止有:

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

任何幫助將非常感激,謝謝!

+0

在LKM中使用類似的代碼進行試驗後,我能夠確定問題是由於試圖將我的套接字綁定到遠程ip造成的!我應該一直使用連接。 – owst 2009-11-30 01:58:10

回答

2

您可能會發現使用UDP的netpoll API更容易。以netconsole爲例說明如何使用它。您正在使用的API更適合用戶空間(您不應該使用段描述符來發送網絡數據!)

+0

從粗略的一瞥中看起來很有希望。謝謝,我會在早上正確地檢查它。 – owst 2009-11-29 03:00:33

+0

netpoll API肯定看起來像我需要的,謝謝 – owst 2009-11-29 11:32:53

0

當您處於文本模式控制檯(即按Ctrl + Alt + F1轉到文本控制檯)時運行您的代碼。這樣內核恐慌會打印出堆棧跟蹤以及任何有關出錯的額外信息。

如果這對您沒有幫助,請使用堆棧跟蹤更新您的問題。

+0

好的提示,我當然得到了堆棧跟蹤,但它很快滾動出視圖(我只能看到最後~25行)。任何方式存儲/管道輸出在某個方便的地方? – owst 2009-11-29 02:58:53

+1

您可以使用串行控制檯,net​​console或可能的kexec崩潰轉儲。 – bdonlan 2009-11-29 03:02:41

0

我不是一個Linux內核開發者,但是你可以在那裏扔一些printk的東西,然後在它關閉之前看dmesg嗎?或者你有沒有想過使用內核調試器?

0

我認爲您應該嘗試將mymethod()函數之外的所有變量都設置爲靜態。請記住,內核堆棧的大小是有限的做8KiB,所以大部分/太大的局部變量可能會導致堆棧溢出和系統掛斷。