自动从内核模块向用户空间应用程序发送消息,而不依赖于输入的调用。来自用户空间

时间:2017-09-17 11:06:10

标签: c linux linux-kernel netlink

我将详细介绍该程序并导致有关使用netlink socket通信的问题 最后一段询问我需要答案的实际问题,所以你可能想先从偷看它开始。

开始前的免责声明:
- 我在问这里之前做了一个早期的搜索,并没有找到完整的解决方案/替代我的问题 - 我知道如何初始化模块并将其插入内核 - 我知道在不使用netlink套接字的情况下处理模块和用户空间之间的通信。使用 struct file_operations func指针赋值的含义以后,只要用户尝试读/写等并使用copy_to_user / copy_from_user回复用户,模块程序就会调用它。 - 本主题涉及Linux OS,Mint 17 dist - 语言是C

好的,我正在构建一个包含3个组件的系统:
1. user.c :用户应用程序(用户在此处键入命令)
2. storage.c :存储设备('虚拟'磁盘锁)
3. device.ko :内核模块(用作1.和2之间的代理。)

该系统的目的是(作为用户)能够:
- 将文件复制到虚拟磁盘设备(2) - 就像上传"上传"来自属于用户的本地目录 - 将文件保存在本地目录中的虚拟设备上 - 例如" download"从设备存储到用户目录。

设计
假设程序(1)(2)已编译并正在使用bash命令成功插入(3)' sudo insmod device.ko ' ,以下应该像这样工作(模拟c):

第1步(在 user.c 中) - >用户类型'下载file.txt'
第2步(在 device.ko 中) - >设备识别出用户试图写入'对它(实际上用户只是传递字符串"下载file.txt")并调用'写'我们之前在module_init()上设置 struct file_operation 的方法的实现。
设备(内核模块)现在将数据(带有命令的字符串)传递给 storage.c 应用程序,期望稍后将答案检索到 user.c 应用程序。
第3步(在 storage.c 中) - >现在,让我们说这个程序执行一个忙碌等待循环的' readmsg()'以及如何触发和识别模块事件的请求,存储设备现在识别出模块已发送请求(带有命令\ data的字符串)。现在,存储程序应该执行一些功能' X'使用sendmsg()在函数内部的某处发送请求的数据。

现在,问题来了。 通常,在我查看的所有示例中,内核模块与用户空间(或 storage.c 程序)之间的通信我们的情况)使用netlink是由用户空间触发而不是相反。意味着来自用户空间的sendmsg()函数调用'请求(struct sk_buff * skb)'方法(在module_init()部分设置如下:

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

所以当storage.c执行类似的操作时:

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

模块调用并运行:

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

从所有那些大块中,我唯一感兴趣的是实际上这样做:

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

但是我无法使用 nlmsg_unicast()而没有strift sk_buff *,只要有来自存储的调用,它就会自动提供给我.c!

总结一切:
如何将msg从device.ko(内核模块)发送到用户空间,而不必等待请求调用/依赖先前显示的&#39;请求()中提供的strcut sk_buff参数&#39;方法?

希望这总结了这一点。 感谢。

0 个答案:

没有答案