我将详细介绍该程序并导致有关使用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;方法?
希望这总结了这一点。 感谢。