Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sockets Linux内核中UDP数据包的发送_Sockets_Udp_Linux Kernel - Fatal编程技术网

Sockets Linux内核中UDP数据包的发送

Sockets Linux内核中UDP数据包的发送,sockets,udp,linux-kernel,Sockets,Udp,Linux Kernel,对于一个项目,我尝试从Linux内核空间发送UDP数据包。我目前正在将我的代码“硬编码”到内核中(我认为这不是最好的/最简单的方法),但我正在尝试一个简单的测试(发送“测试”)。值得一提的是,我是内核黑客的新手——我对很多原理和技术都不太了解 每次我的代码运行时,系统都会挂起,我必须重新启动-没有鼠标/键盘响应,滚动键和大写锁定键同时闪烁-我不确定这意味着什么,但我假设这是内核死机 这个测试代码不需要重复发送代码,但是当它工作时,我想发送可能需要多个“发送”的大消息-我不确定是否可能是我的问题的

对于一个项目,我尝试从Linux内核空间发送UDP数据包。我目前正在将我的代码“硬编码”到内核中(我认为这不是最好的/最简单的方法),但我正在尝试一个简单的测试(发送“测试”)。值得一提的是,我是内核黑客的新手——我对很多原理和技术都不太了解

每次我的代码运行时,系统都会挂起,我必须重新启动-没有鼠标/键盘响应,滚动键和大写锁定键同时闪烁-我不确定这意味着什么,但我假设这是内核死机

这个测试代码不需要重复发送代码,但是当它工作时,我想发送可能需要多个“发送”的大消息-我不确定是否可能是我的问题的原因

注意:这段代码被插入到linux source/net/core/origin的NEIGH.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);
}
void mymethod()
{
结构插座;
addr_in中的结构sockaddr_;
国际检索;
无符号短端口=htons(2048);
unsigned int host=in_aton(“192.168.1.254”);
无符号整数长度=5;
char*buf=“测试\0”;
结构msghdr msg;
结构iovec iov;
int len=0,writed=0,left=length;
mm_段\u t旧mm;
NEIGH_PRINTK1(“将sk_buff转发到:%p.\n”,skb);
如果((ret_val=sock_create(PF_INET、sock_DGRAM、IPPROTO_UDP和sock))<0){
NEIGH_PRINTK1(“创建套接字时出错;正在终止。代码:%d\n”,ret_val);
返回;
}
memset(&addr_in,0,sizeof(struct sockaddr_in));
addr_in.sin_family=AF_INET;
addr_in.sin_port=端口;
addr_in.sin_addr.s_addr=主机;
如果((ret_val=sock.ops->bind(&sock,(struct sockaddr*)和addr_in,sizeof(struct sockaddr_in)))<0){
NEIGH_PRINTK1(“尝试绑定套接字时出错。代码:%d\n”,ret_val);
转到关闭;
}
memset(&msg,0,sizeof(struct-msghdr));
msg.msg_标志=0;
msg.msg_name=&addr_in;
msg.msg_namelen=sizeof(结构sockaddr_in);
msg.msg_iov=&iov;
msg.msg_iovlen=1;
msg.msg_control=NULL;
msg.msg_controllen=0;
重复发送:
msg.msg_iov->iov_len=左;
msg.msg_iov->iov_base=(char*)buf+写入;
oldmm=get_fs();
set_fs(内核_DS);
len=sock_sendmsg(&sock,&msg,左);
集_fs(oldmm);
如果(len==-ERESTARTSYS)
转到重复发送;
如果(len>0){
书面+=len;
左-=len;
如果(左)
转到重复发送;
}
关闭:
sock_释放(&sock);
}

非常感谢您的帮助,谢谢

在文本模式控制台中运行代码(即按Ctrl+Alt+F1转到文本控制台)。这样,内核死机将打印出堆栈跟踪和关于出错原因的任何额外信息


如果这对您没有帮助,请使用堆栈跟踪更新您的问题。

我不是一个Linux内核开发人员,但是您能在那里添加一些printk并在dmesg崩溃之前查看它吗?或者您考虑过使用内核调试器吗?

您可能会发现使用UDP更容易。请看一个如何使用它的示例。您使用的API更适合用户空间(您不必使用段描述符来发送网络数据!)

我认为您应该尝试将所有变量置于mymethod()函数之外,并使它们成为静态变量。请记住,内核堆栈的大小限制为do 8KiB,因此太多/太大的局部变量可能会导致堆栈溢出和系统挂起。

好提示,我当然得到了堆栈跟踪,但它很快就从视图中滚了出去(我只能看到最后25行)。有没有办法将输出存储/管道化到方便的地方?您可以使用串行控制台、netconsole,或者可能使用kexec崩溃转储。粗略地看,这看起来很有希望。谢谢,我会在早上正确地检查它。在LKM中尝试使用类似的代码后,我能够确定问题是由于试图将我的套接字绑定到远程ip引起的!我应该用connect来代替。