jiufei19 发表于 2010-06-01 12:06

netlink_kernel_create函数调用时的问题【已解决】

本帖最后由 jiufei19 于 2010-06-02 10:58 编辑

大家好,我按照CU中介绍的关于netlink原理的例子(netlink socket 编程之 why & how )在我本地机器上进行编译,我的内核版本2.6.23.1-42.fc8,在调用到netlink_kernel_create函数时,总是有如下警告,望各位赐教如何消除此警告:

-----------------------------------------------------
netlink_k.c:19: 警告:函数声明不是一个原型
netlink_k.c: In function ‘netlink_test’:
netlink_k.c:25: 警告:传递参数 4 (属于 ‘netlink_kernel_create’)时在不兼容的指针类型间转换
-----------------------------------------------------

下面我将netlink_k.c的源码例在下面:

1 #include <linux/socket.h>
2 #include <linux/netlink.h>
3 #include <net/sock.h>
4 #include <linux/kernel.h>
5 #include <linux/module.h>
6 #include <linux/init.h>
7
8 #define NETLINK_TEST 17
9 #define MAX_PAYLOAD 1024
10
11 struct sock *nl_sk = NULL;
12
13 void nl_data_ready (struct sock *sk, int len)
14 {
15   wake_up_interruptible(sk->sk_sleep);
16 }
17
18 void netlink_test()
19 {
20   struct sk_buff *skb = NULL;
21   struct nlmsghdr *nlh = NULL;
22   int err;
23   unsigned long pid;
24
25   nl_sk = netlink_kernel_create(NETLINK_TEST, 0, NULL, nl_data_ready, THIS_MODULE);
26   /* wait for message coming down from user-space */
27   skb = skb_recv_datagram(nl_sk, 0, 0, &err);
28
29   nlh = (struct nlmsghdr *)skb->data;
30   printk("%s: received netlink message payload:%s\n",
31         __FUNCTION__, (char *)NLMSG_DATA(nlh));
32
33   pid = nlh->nlmsg_pid; /*pid of sending process */
34   /*NETLINK_CB(skb).groups = 0; [> not in mcast group <]*/
35   /*NETLINK_CB(skb).pid = 0;      [>from kernel <]*/
36   NETLINK_CB(skb).pid = pid;
37   NETLINK_CB(skb).dst_group = 0;/* unicast */
38   netlink_unicast(nl_sk, skb, pid, MSG_DONTWAIT);
39   sock_release(nl_sk->sk_socket);
40 }
41
42 static int __init hello_start(void)
43 {
44   printk("Loading netlink demo module...\n");
45
46   netlink_test();
47   return 0;
48 }
49
50 static void __exit hello_end(void)
51 {
52   printk("Exiting netlink demo module...\n");
53 }
54
55 module_init(hello_start);
56 module_exit(hello_end);

另外,我还存在如下两个疑问:

1、因为我的内核版本中netlink_kernel_create函数原型如下,其中增加了struct mutex *cb_mutex这个参数,我这里用NULL来进行调用,是否正确?
netlink_kernel_create(int unit, unsigned int groups,void (*input)(struct sock *sk, int len),struct mutex *cb_mutex, struct module *module)
2、对于这个参数NETLINK_CB(skb).pid,到底填什么?因为2.6.23内核中已经没有dst_pid了,所以这里的pid到底是什么呢?

Godbach 发表于 2010-06-01 13:15

LZ先明确一下内核版本是否一致。netlink的接口在2.4和2.6中是有所变化的。

jiufei19 发表于 2010-06-01 13:51

回复 2# Godbach


    我的内核版本的确和CU上给出的这篇文章的版本不一致,于是我进行了对应的修改,本帖就是对修改后的一些错误现象的求助

Godbach 发表于 2010-06-01 13:55

其实LZ可以直接参考内核代码的实现。比如ip_queue.c中在模块入口ip_queue_init中也调用了netlink_kernel_create,看看人家是怎么传递参数的。

jiufei19 发表于 2010-06-01 14:23

本帖最后由 jiufei19 于 2010-06-01 14:33 编辑

回复 4# Godbach


    谢谢!果然根据斑竹的提示,在ip_queue_init中使用了NULL作为了调用时的实参:
   ipqnl = netlink_kernel_create(NETLINK_FIREWALL, 0, ipq_rcv_sk,NULL, THIS_MODULE);

    晕,我自己粗心大意了,谢谢!

   现在还剩最后1个问题:netlink_k.c|19| 警告:函数声明不是一个原型

   请问此问题是什么原因造成?

Godbach 发表于 2010-06-01 14:33

25   nl_sk = netlink_kernel_create(NETLINK_TEST, 0, NULL, nl_data_ready, THIS_MODULE);
仔细看看这行代码有什么问题。

jiufei19 发表于 2010-06-01 14:35

回复 6# Godbach


    谢谢指正,我刚才的发帖已经纠正了这个粗心的错误,请问刚才那个警告是什么原因?

Godbach 发表于 2010-06-01 14:37

netlink_kernel_create(int unit, unsigned int groups,void (*input)(struct sock *sk, int len),struct mutex *cb_mutex, struct module *module)
你看看你实际调用的时候,各个参数类型是否正确。
倒数第二个参数是什么类型,你传递进去的是什么类型?

jiufei19 发表于 2010-06-01 14:45

回复 8# Godbach


    我的实际调用语句如下,倒数第2个参数是NULL

   nl_sk = netlink_kernel_create(NETLINK_TEST, 0, nl_data_ready, NULL, THIS_MODULE);

    另外,在仍然有此警告的情况下,内核模块和用户态程序之间的通信过程成功了,在此我将代码完整贴出来,供大家参考,并请斑竹帮我解决刚才那个警告问题


    1 #include <linux/socket.h>
    2 #include <linux/netlink.h>
    3 #include <net/sock.h>
    4 #include <linux/kernel.h>
    5 #include <linux/module.h>
    6 #include <linux/init.h>
    7
    8 #define NETLINK_TEST 17
    9 #define MAX_PAYLOAD 1024
   10
   11 struct sock *nl_sk = NULL;
   12
   13 void nl_data_ready (struct sock *sk, int len)
   14 {
   15   wake_up_interruptible(sk->sk_sleep);
   16 }
   17
   18 void netlink_test()
   19 {
   20   struct sk_buff *skb = NULL;
   21   struct nlmsghdr *nlh = NULL;
   22   int err;
   23   unsigned long pid;
   24
   25   nl_sk = netlink_kernel_create(NETLINK_TEST, 0, nl_data_ready, NULL, THIS_MODULE);
   26   /* wait for message coming down from user-space */
   27   skb = skb_recv_datagram(nl_sk, 0, 0, &err);
   28
   29   nlh = (struct nlmsghdr *)skb->data;
   30   printk("%s: received netlink message payload:%s\n",
   31         __FUNCTION__, (char *)NLMSG_DATA(nlh));
   32
   33   pid = nlh->nlmsg_pid; /*pid of sending process */
   34   NETLINK_CB(skb).pid = pid;
   35   NETLINK_CB(skb).dst_group = 0;/* unicast */
   36   netlink_unicast(nl_sk, skb, pid, MSG_DONTWAIT);
   37   sock_release(nl_sk->sk_socket);
   38 }   
   39
   40 static int __init hello_start(void)
   41 {
   42   printk("Loading netlink demo module...\n");
   43
   44   netlink_test();
   45   return 0;
   46 }
   47
   48 static void __exit hello_end(void)
   49 {
   50   printk("Exiting netlink demo module...\n");
   51 }
   52
   53 module_init(hello_start);
   54 module_exit(hello_end);

    用户态程序:

    1 #include <stdio.h>
    2 #include <string.h>
    3 #include <stdlib.h>
    4 #include <sys/types.h>
    5 #include <sys/socket.h>
    6 #include <linux/netlink.h>
    7
    8 #define NETLINK_TEST 17
    9 #define MAX_PAYLOAD 1024/* maximum payload size*/
   10
   11 struct sockaddr_nl src_addr, dest_addr;
   12 struct nlmsghdr *nlh = NULL;
   13 struct iovec iov;
   14 struct msghdr msg;
   15 int sock_fd;
   16
   17 int main() {
   18   sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_TEST);
   19
   20   memset(&src_addr, 0, sizeof(src_addr));
   21   src_addr.nl_family = AF_NETLINK;
   22   src_addr.nl_pid = getpid();/* self pid */
   23   src_addr.nl_groups = 0;/* not in mcast groups */
   24   bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr));
   25
   26   memset(&dest_addr, 0, sizeof(dest_addr));
   27   dest_addr.nl_family = AF_NETLINK;
   28   dest_addr.nl_pid = 0;   /* For Linux Kernel */
   29   dest_addr.nl_groups = 0; /* unicast */
   30
   31   nlh=(struct nlmsghdr *)malloc(
   32                  NLMSG_SPACE(MAX_PAYLOAD));
   33   /* Fill the netlink message header */
   34   nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
   35   nlh->nlmsg_pid = getpid();/* self pid */
   36   nlh->nlmsg_flags = 0;
   37   /* Fill in the netlink message payload */
   38   strcpy(NLMSG_DATA(nlh), "Hello you!");
   39
   40   iov.iov_base = (void *)nlh;
   41   iov.iov_len = nlh->nlmsg_len;
   42   msg.msg_name = (void *)&dest_addr;
   43   msg.msg_namelen = sizeof(dest_addr);
   44   msg.msg_iov = &iov;
   45   msg.msg_iovlen = 1;
   46
   47   sendmsg(sock_fd, &msg, 0);
   48
   49   /* Read message from kernel */
   50   memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
   51   recvmsg(sock_fd, &msg, 0);
   52   printf(" Received message payload: %s\n", NLMSG_DATA(nlh));
   53
   54   /* Close Netlink Socket */
   55   close(sock_fd);
   56
   57   return 0;
   58 }

    Makefile:

   1 obj-m = netlink_k.o
    2 KVERSION = $(shell uname -r)
    3 all:
    4   make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
    5   gcc netlink_u.c -o netlink_u
    6 clean:
    7   make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean

Godbach 发表于 2010-06-01 14:54

回复Godbach


    我的实际调用语句如下,倒数第2个参数是NULL

   nl_sk = netlink_kernel_creat ...
jiufei19 发表于 2010-06-01 14:45 http://linux.chinaunix.net/bbs/images/common/back.gif


还有警告吗,警告信息是什么,贴出来。
页: [1] 2
查看完整版本: netlink_kernel_create函数调用时的问题【已解决】