【发布时间】:2014-10-08 20:04:26
【问题描述】:
我要完成的任务实际上很简单(将字符串“TEST”多播到用户级守护程序),但内核模块无法编译。它因错误而停止:
passing argument 4 of ‘genlmsg_multicast_allns’ makes integer from pointer without a cast [enabled by default]
但不应该只是我定义的多播组吗?
这里是“澄清”的代码:
#include <linux/module.h>
#include <net/sock.h>
#include <linux/netlink.h>
#include <linux/skbuff.h>
#include <linux/string.h>
#include <net/netlink.h>
#include <net/genetlink.h>
struct sock *nl_sk = NULL;
static void daemon(void){
struct sk_buff *skb;
void* msg_head;
unsigned char *msg;
struct genl_family my_genl_family = {
.id = GENL_ID_GENERATE,
.hdrsize = 0,
.name = "family_name",
.version = 1,
.maxattr = 5
};
struct genl_multicast_group my_mc_group = {
.name = "mc_group",
};
msg = "TEST";
skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
msg_head = genlmsg_put(skb, 0, 0, &my_genl_family, 0, 21);
nla_put(skb, 0, sizeof(msg), msg);
genlmsg_end(skb, msg_head);
genlmsg_multicast_allns( &my_genl_family, skb, 0, my_mc_group, GFP_KERNEL);
}
static int __init hello_init(void)
{
printk("Entering: %s\n", __FUNCTION__);
printk(KERN_INFO "Calling main function with sockets\n");
struct netlink_kernel_cfg cfg = {
.groups = 1,
.flags = NL_CFG_F_NONROOT_RECV,
};
nl_sk = netlink_kernel_create(&init_net, NETLINK_GENERIC, &cfg);
daemon();
return 0;
}
static void __exit hello_exit(void)
{
printk(KERN_INFO "exiting hello module\n");
netlink_kernel_release(nl_sk);
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
感谢您的帮助。
编辑
这是客户端代码:
#include <netlink/netlink.h>
#include <netlink/socket.h>
#include <netlink/msg.h>
#include <netlink/genl/genl.h>
#include <linux/genetlink.h>
/*
* This function will be called for each valid netlink message received
* in nl_recvmsgs_default()
*/
static int my_func(struct nl_msg *msg, void *arg)
{
//struct nl_msg *nlmsg = nlmsg_alloc_size(GENL_HDRLEN+nla_total_size(sizeof(msg))+36);
printf("Test\n");
return 0;
}
int main(){
struct nl_sock *sk;
int gr_id;
/* Allocate a new socket */
sk = nl_socket_alloc();
/*
* Notifications do not use sequence numbers, disable sequence number
* checking.
*/
nl_socket_disable_seq_check(sk);
/*
* Define a callback function, which will be called for each notification
* received
*/
nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, my_func, NULL);
/* Connect to netlink generic protocol */
nl_connect(sk, NETLINK_GENERIC);
gr_id = genl_family_get_id("family_name");
/* Subscribe to link notifications group */
nl_socket_add_memberships(sk, gr_id, 0);
/*
* Start receiving messages. The function nl_recvmsgs_default() will block
* until one or more netlink messages (notification) are received which
* will be passed on to my_func().
*/
while (1){
nl_recvmsgs_default(sk);
}
return 0;
}
【问题讨论】:
-
您需要在该调用中使用整数,而不是 struct genl_multicast_group。看看它是如何在内核的其他地方完成的。还要注意这个整数有一个上限,比如 32。
-
感谢您的评论。是的,上限是 32。我会尝试编译更正的版本。
-
所以内核模块的编译是成功的(感谢和抱歉,我不能支持你的评论..)。但我仍然无法在用户空间接收消息。 (正如信息:它确实编译了最后一次,上面的“错误”只是一个警告,它似乎不是问题的根源。)
-
我最近在使用 netlink 套接字在内核驱动程序和守护程序之间进行通信时遇到了类似的问题。似乎 netlink 套接字的使用方式存在限制。有些人建议使用多路复用套接字。我只是放弃并使用了第一次工作的 UDP 套接字。如果您有兴趣,我可以发布示例代码。
-
是的,我认为我的代码应该可以为发生的某些内核事件简单地发送多播。如果您能提供代码,那就太好了!非常感谢!
标签: c linux-kernel kernel-module multicast netlink