Linux内核模块通过UNIX套接字与用户空间通信

t98cgbkg  于 2023-06-29  发布在  Unix
关注(0)|答案(1)|浏览(129)

本文尝试使用UNIX套接字来实现内核模块与用户空间的通信,内核模块作为客户端,用户空间程序作为服务器。
我注意到UNIX套接字有三种类型的地址(参考“man 7 unix”)。
当我使用路径名类型地址时,它工作正常。但是当我使用抽象类型地址时,内核模块无法连接到服务器。它返回-ECONNREFUSED。
我的代码有什么问题吗?

内核代码

struct sockaddr_un s_addr;

    ret = sock_create_kern(&init_net, AF_LOCAL, SOCK_STREAM, 0, &cl_sock);
    if (ret < 0) {
        /*...*/
    }

    memset(&s_addr, 0, sizeof(struct sockaddr_un));
    s_addr.sun_family = AF_LOCAL;
    s_addr.sun_path[0] = 0;
    strncpy(s_addr.sun_path + 1, "my_test", sizeof(s_addr.sun_path) - 1);

    ret = cl_sock->ops->connect(cl_sock, (struct sockaddr *)&s_addr, sizeof(s_addr), 0);
    if (ret < 0) {
        /*...*/
    }

服务端代码

server_socket = socket_local_server("my_test", ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
 if (server_socket < 0) {
    /*...*/
 }
 accept(server_socket , NULL, NULL);

我希望使用抽象类型地址连接到服务器。

cotxawn7

cotxawn71#

试试这个:

socklen_t len = offsetof(struct sockaddr_un, sun_path) + 1 +
                    strlen("my_test");
    ret = cl_sock->ops->connect(cl_sock,
                                (struct sockaddr *)&s_addr,
                                len, // <-- not sizeof(s_addr)
                                0);

在抽象名称空间中,必须计算 sun_path 中地址的确切长度,作为 sockaddr 大小的一部分。您想要的地址是"\0my_test",但您传入了完整的sizeof(s_addr),这意味着指定的地址类似于"\0my_test\0\0\0\0\0\0\0\0\0\0\0\0\0..."-不同的套接字。
(By相反,路径名本地套接字被理解为具有终止空字节。"/tmp/my_test\0""/tmp/my_test\0\0\0\0..."都引用套接字文件/tmp/my_test
Linux man page for unix sockets在处理AF_UNIX地址格式时解决了这个问题,尽管可能不像匆忙的程序员希望的那样清楚。

相关问题