最近在学习netlink,用来实现用户层和内核的通信,在写内核部分代码时,遇到一个奇怪的问题:
        每次卸载完模块后,必须修改协议号(NETLINK_TEST),netlink_kernel_create(&init_net,NETLINK_TEST,&cfg);才能成功,不修改协议号,一直创建内核sock失败,
        哪位大佬帮帮忙!!!所用平台Ubuntu16.04+linux内核4.15.0-46-generic内核代码如下#include<linux/module.h>
#include<linux/netlink.h>
#include<linux/skbuff.h>
#include<net/sock.h>#define MAX_MSG_LEN 1024
//#define USER_PID 66666
#define NETLINK_TEST 21 //proto number 
   static struct sock* g_sk_nl_k = NULL;
static struct nlmsghdr *g_nlh = NULL;  //will contain user's pid,data and so on//static int g_nlmsg_pid = USER_PID;//static void revFromApp(struct sk_buff* skb);//send msg to app
int sendToApp(char *pmsg){
    struct nlmsghdr *nlh = NULL;
    struct sk_buff *nl_skb_out = NULL;
    int ret;
    ret= -1;    if(!pmsg){
        printk("Msg is null,send msg failed!\n");
        return -1;
    }    if(!g_sk_nl_k){
        printk("User's pid is'n known,send msg failed!\n");
        return -1;
    }
  
    nl_skb_out = nlmsg_new(MAX_MSG_LEN,0);//Allocate a new skb to send a new netlink message to nl_APP
    //nl_skb_out = alloc_skb(NLMSG_SPACE(MAX_MSG_LEN), GFP_ATOMIC);
    if(!nl_skb_out){
        printk("Allocate new skb failed,send msg failed!\n");
        return -1;
    }
    
    nlh = nlmsg_put(nl_skb_out,0,0,0,MAX_MSG_LEN,0);
    if(nlh == NULL){
        printk("nlmsg_put failaure!\n");
        nlmsg_free(nl_skb_out);
        return -1;
    }    NETLINK_CB(nl_skb_out).creds.pid = 0;
    //NETLINK_CB(nl_skb_out).dst_group = 0;
    memcpy(NLMSG_DATA(nlh), pmsg, strlen(pmsg)); 
    
    //ret = nlmsg;
    ret = netlink_unicast(g_sk_nl_k, nl_skb_out,g_nlh->nlmsg_pid, MSG_DONTWAIT);//USER_PID
    if(ret < 0){
        printk("nlmsg_unicast failaure!\n");
        nlmsg_free(nl_skb_out);
        return -1;
    }
    nlmsg_free(nl_skb_out);
    return 0;    
}//receive msg from app(only run one time if no loop)
static void revFromApp(struct sk_buff* skb){
    char * msgFromApp = NULL;
    char * str0 = "msg from kernel";
    //struct nlmsghdr *nlh; turn to gloabe 
    g_nlh=(struct nlmsghdr*)(skb->data); //nlh message from shb's data...(sk_buff:unsigned char *data)
    //nlh = nlmsg_hdr(skb);
    
    msgFromApp = nlmsg_data(g_nlh);//get data from struct nlmsghdr *nlh;
    
    //test
    printk("msg:%s\n",msgFromApp);
    
    
    sendToApp(str0);
}struct netlink_kernel_cfg cfg = {
    .input=revFromApp,
    };//create socket
int netlinkCreate(void){
    
    g_sk_nl_k = netlink_kernel_create(&init_net,NETLINK_TEST,&cfg);
    if(!g_sk_nl_k){
        printk("Error creating socket!\n");
        return -1;
    } 
    return 0;
}//close socket
void netlinkClose(struct sock* sk_nl_k){
    if(!sk_nl_k){
        
        //sock_release(sk_nl_k->sk_socket); 
        netlink_kernel_release(sk_nl_k);
        //sk_nl_k = NULL;
    }   
}//netlink open
static int __init netlink_init(void){
    int ret = -1;   
    ret = netlinkCreate();//get struct sock* g_sk_nl_k
    if(ret < 0){
    printk("Netlink open failed!\n");
    return -1;
    }
    printk("Netlink open !\n");
    return 0;
}//netlink close
static void __exit netlink_exit(void){
    //netlink_kernel_release(g_sk_nl_k);
    //printk("Netlink close0!\n");
    netlinkClose(g_sk_nl_k);
    printk("Netlink close1!\n");
}module_init(netlink_init);  
module_exit(netlink_exit);  
MODULE_LICENSE("GPL");  
MODULE_AUTHOR("ysx"); 
makefile如下:ifneq ($(KERNELRELEASE),)obj-m :=nldrv.o
#obj-m += hello.oelseKDIR :=/lib/modules/$(shell uname -r)/buildall:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -f *.ko *.o *.mod.o *.mod.c *.symvers *.orderendif