简体   繁体   English

在不依赖输入调用的情况下,自动将消息从内核模块发送到用户空间应用程序。 来自用户空间

[英]Autonomically sending a message from kernel-module to user-space application without relying on the invoke of input. from user-space

I will give a detailed exp of the program and lead to the issue regarding the use of.netlink socket communication.我将给出程序的详细说明,并引出有关使用.netlink 套接字通信的问题。
The last paragraph asks the actual question I need an answer for, so you might wanna start by peeking it first.最后一段问了我需要回答的实际问题,所以你可能想先看看它。

Disclaimer before I start:开始之前的免责声明:
- I have made an earlier search before asking here and did not find complete solution / alternative to my issue. - 我在这里提问之前进行了较早的搜索,但没有找到我的问题的完整解决方案/替代方案。
- I know how to initialize a module and insert it to kernel. - 我知道如何初始化一个模块并将其插入到 kernel。
- I know to handle communication between module and user-space without using.netlink sockets . - 我知道在不使用 .netlink sockets的情况下处理模块和用户空间之间的通信。 Meaning using struct file_operations func pointers assignments to later be invoked by the module program whenever a user attempts to read/write etc. and answer to the user using copy_to_user / copy_from_user.意思是使用struct file_operations func 指针赋值,以便稍后在用户尝试读/写等时由模块程序调用,并使用 copy_to_user / copy_from_user 回答用户。
- This topic refers to Linux OS, Mint 17 dist. - 本主题涉及 Linux 操作系统,Mint 17 dist。
- Language is C - 语言是 C

Okay, so I am building a system with 3 components:好的,所以我正在构建一个包含 3 个组件的系统:
1. user.c : user application (user types commands here) 1. user.c :用户应用程序(用户在此处键入命令)
2. storage.c : storage device ('virtual' disk-on-key) 2. storage.c :存储设备(“虚拟”磁盘密钥)
3. device.ko : kernel module (used as proxy between 1. and 2.) 3. device.ko : kernel 模块(用作 1. 和 2. 之间的代理)

The purpose of this system is to be able (as a user) to:该系统的目的是能够(作为用户):
- Copy files to the virtual disk-on-key device (2) - like an "upload" from local directory that belongs to the user. - 将文件复制虚拟磁盘密钥设备 (2) - 就像从属于用户的本地目录“上传”一样。
- Save files from the virtual device on local directory - like "download" from the device storage to the user directory. - 将文件虚拟设备保存到本地目录 - 就像从设备存储“下载”到用户目录。

Design:设计:
Assuming programs (1) , (2) are compiled and running + (3) has successfully inserted using the bash command ' sudo insmod device.ko ', the following should work like this (simulation ofc):假设程序(1)(2)已编译并运行 + (3)已使用 bash 命令“ sudo insmod device.ko ”成功插入,以下应该像这样工作(模拟 ofc):

Step 1 (in user.c ) -> user types 'download file.txt'第 1 步(在user.c中)-> 用户输入“下载文件.txt”
Step 2 (in device.ko ) -> the device recognizes the user have tried to 'write' to it (actually user just passing the string "download file.txt") and invokes the 'write' implementation of the method we set on struct file_operation earlier on module_init().第 2 步(在device.ko中)-> 设备识别出用户已尝试“写入”它(实际上用户只是传递字符串“download file.txt”)并调用我们设置的方法的“写入”实现早先在 module_init() 上构造file_operation
The device (kernel module) now passes the data (string with a command) to the storage.c application, expecting an answer to later be retrieved to the user.c application.设备(内核模块)现在将数据(带有命令的字符串)传递给storage.c应用程序,期望稍后将答案检索给user.c应用程序。
Step 3 (in storage.c ) -> now, lets say this program performs a busy-wait loop of 'readmsg()' and that's how a request from module event is triggered and recognized, the storage device now recognizes that the module has sent a request (string with a command \ data).第 3 步(在storage.c中)-> 现在,假设该程序执行一个“readmsg()”的忙等待循环,这就是触发和识别来自模块事件的请求的方式,存储设备现在识别出模块具有发送了一个请求(带有命令\数据的字符串)。 Now, the storage programs shall perform an implementation of some function 'X' to send the data requested using sendmsg() somewhere inside the function.现在,存储程序应执行一些 function 'X' 的实现,以使用 function 内某处的 sendmsg() 发送请求的数据。

Now, here comes the issue.现在,问题来了。 Usually, on all of the examples I've looked on web, the communication between the kernel-module and a user-space (or the storage.c program in our case) using.netlink is triggered by the user-space and not vice versa.通常,在我看过 web 的所有示例中,内核模块和用户空间(或我们的示例中的storage.c程序)之间的通信使用 .netlink 是由用户空间触发的,而不是由用户空间触发的反之亦然。 Meaning that the sendmsg() function from the user-space invokes the 'request(struct sk_buff *skb)' method (which is set on the module_init() part as following:这意味着来自用户空间的 sendmsg() function 调用'request(struct sk_buff *skb)'方法(在 module_init() 部分设置如下:

struct netlink_kernel_cfg cfg = {
    .input = request            // when storage.c sends something, it invokes the request function
};

so when the storage.c performs something like:所以当 storage.c 执行类似的操作时:

sendmsg(sock_fd,&msg,0);                        // send a msg to the module

the module invokes and runs the:该模块调用并运行:

static void request(struct sk_buff *skb) {
    char *msg ="Hello from kernel";
    msg_size=strlen(msg);

    netlink_holder=(struct nlmsghdr*)skb->data;
    printk(KERN_INFO "Netlink received msg payload:%s\n",(char*)nlmsg_data(netlink_holder));

    pid = netlink_holder->nlmsg_pid;                                // pid of sending process 

    skb_out = nlmsg_new(msg_size,0);

    if(!skb_out){
        printk(KERN_ERR "Failed to allocate new skb\n");
        return;
    } 

    netlink_holder=nlmsg_put(skb_out,0,0,NLMSG_DONE,msg_size,0);    // add a new netlink message to an skb. more info: http://elixir.free-electrons.com/linux/v3.2/source/include/net/netlink.h#L491
    NETLINK_CB(skb_out).dst_group = 0;                              // not in multicast group
    strncpy(nlmsg_data(netlink_holder),msg,msg_size);               // assign data as char* (variable msg) 
    result=nlmsg_unicast(sock_netlink,skb_out,pid);                 // send data to storage. more info: http://elixir.free-electrons.com/linux/latest/source/include/net/netlink.h#L598

    if(result<0)
        printk(KERN_INFO "Error while sending bak to user\n");
}

and from all that big chunk, the only thing that im interesting in is actually doing this:从所有那么大的块中,我唯一感兴趣的就是这样做:

result=nlmsg_unicast(sock_netlink,skb_out,pid);                 // send data to storage.

BUT I can't use nlmsg_unicast() without having the strcut sk_buff* which is provided automatically for me whenever there's an invoke from storage.c !但是如果没有 strcut sk_buff* ,我就不能使用nlmsg_unicast() ,只要有来自 storage.c 的调用,它就会自动为我提供!

To sum up everything:总结一切:
How do I send a msg from the device.ko (kernel module) to the user-space withtout having to wait for request to invoke / rely on the provided strcut sk_buff parameter from the earlier shown 'request()' method?如何从 device.ko(内核模块)向用户空间发送消息,而不必等待请求调用/依赖前面显示的“request()”方法中提供的 strcut sk_buff 参数?

Hope this sums up the point.希望这总结了这一点。 Thanks.谢谢。

The only question here is that you need the user-space program connected to kernel-space first to get the pid of your user-program.这里唯一的问题是您需要首先连接到内核空间的用户空间程序才能获取用户程序的 pid。

After get the pid, you can manually construct the skb_out and send it out through netlink_unicast or nlmsg_unicast .得到pid后,可以手动构造skb_out,通过netlink_unicastnlmsg_unicast发送出去。

The pid is always needed, you can set it as static and let your user-space program connect to your device.ko to make a long-maintained link. pid 总是需要的,您可以将其设置为 static 并让您的用户空间程序连接到您的 device.ko 以建立长期维护的链接。

Although this question is asked at 2017, I believe OP has already found the answer:D虽然这个问题是在 2017 年提出的,但我相信 OP 已经找到了答案:D

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM