netlink实现用户态和内核态数据交互

本文代码实现:用户进程发送“nihao”给内核,内核回复“niyehao”给用户态。

1:netlink.h添加自己的宏。
2:编写用户态程序。
3:编写内核态程序。

内核态,需要全局变量进行数据的交互。


在模块init的时候,可以:

netlinkfd = netlink_kernel_create(&init_vrf, NL_MY, 0, kernel_receive, NULL, THIS_MODULE);

NL_MY 是加在 netlink.h 头文件中的宏。
kernel_recv 是自定义的函数的地址,用以接收处理用户态的数据
int process_message_thread(void *arg)
{
    struct sk_buff *skb = (struct sk_buff *)(arg);
    struct sk_buff *newskb;
    int opp_id;
    struct struReq_s *msg = (struct struReq_s *) skb->data;
    opp_id = msg->pid;

    struct struReq_s *needtosend = kmalloc(sizeof(struct struReq_s) + strlen("niyehao"),GFP_KERNEL);
    needtosend->data_len = strlen("niyehao");
    memcpy(needtosend->data,"niyehao", needtosend->data_len);
    newskb = alloc_skb(sizeof(struct struReq_s) + strlen("niyehao"), GFP_ATOMIC);
    skb_put(newskb,sizeof(struct struReq_s) + strlen("niyehao"));
    memcpy(newskb->data,needtosend,sizeof(struct struReq_s) + strlen("niyehao"));
    netlink_unicast(netlinkfd, newskb, opp_id, MSG_DONTWAIT);
    kfree(needtosend);
    return 0;
}
u32 nt = 0;
void kernel_receive(struct sk_buff *skb)
{
    printk("#########recv###########\n");
    process_message_thread(skb);
    printk("#########leave###########\n");
}

用户态程序:

int netlink_socket = -1;

int main()
{
    
    struct sockaddr_nl src_addr;
    s32 ret;

    struct struReq_s
    {
        int pid;
        int data_len;
        char data[0];
    };
    u8 buf[1024] = {0};
    struct struReq_s *struReq = NULL;
    netlink_socket = socket(AF_NETLINK, SOCK_RAW, NL_MY);
    if(netlink_socket < 0)
    {
        return -1;
    }
    memset(&src_addr, 0, sizeof(src_addr));
    src_addr.nl_family = AF_NETLINK;
    src_addr.nl_pid = getpid();
    src_addr.nl_groups = 1;
        
    ret = bind(netlink_socket, (struct sockaddr *)&src_addr, sizeof(src_addr));
    if(ret < 0)
    {
        return -1;
    }
    struReq = malloc(sizeof( struct struReq_s) + 10);
    if(struReq == NULL)
    {
        printf("malloc fail\n");
        return 0;
    }
    memset(struReq, 0, sizeof(struct struReq_s) + 10);

    struReq->pid = getpid();
    struReq->data_len = 10;
    memcpy(struReq->data,"nihao",strlen("nihao"));
    
    memset(&src_addr, 0, sizeof(src_addr));    
    src_addr.nl_family = AF_NETLINK;    
    src_addr.nl_pid = 0;    
    src_addr.nl_groups = 0; 
    if(sendto(netlink_socket, struReq, struReq->data_len + sizeof(struct struReq_s), 0,        
        (struct sockaddr *)&src_addr, sizeof(src_addr)) < 0)    
    {
        return -1;     
    }
    
    printf("user recv\n");
    /*阻塞的读*/
    memset(buf,0,1024);
    recv(netlink_socket,buf,1024,0);
    printf("recv from kernel len : %d\n",((struct struReq_s *)buf)->data_len);
    printf("recv from kernel data: %s\n",((struct struReq_s *)buf)->data);
    
    free(struReq);
    close(netlink_socket);
    return 0;
}



你可能感兴趣的:(Liunx内核)