免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
linux netlink通信機(jī)制

一、什么是Netlink通信機(jī)制

   Netlink套接字是用以實(shí)現(xiàn)用戶進(jìn)程與內(nèi)核進(jìn)程通信的一種特殊的進(jìn)程間通信(IPC) ,也是網(wǎng)絡(luò)應(yīng)用程序與內(nèi)核通信的最常用的接口。

    Netlink 是一種特殊的 socket,它是 Linux 所特有的,類似于 BSD 中的AF_ROUTE 但又遠(yuǎn)比它的功能強(qiáng)大,目前在Linux 內(nèi)核中
    使用netlink 進(jìn)行應(yīng)用與內(nèi)核通信的應(yīng)用很多; 包括:路由 daemon(NETLINK_ROUTE),用戶態(tài) socket 協(xié)議(NETLINK_USERSOCK),
    防火墻(NETLINK_FIREWALL),netfilter 子系統(tǒng)(NETLINK_NETFILTER),內(nèi)核事件向用戶態(tài)通知(NETLINK_KOBJECT_UEVENT),
    通用 netlink(NETLINK_GENERIC)等。
    
    Netlink 是一種在內(nèi)核與用戶應(yīng)用間進(jìn)行雙向數(shù)據(jù)傳輸?shù)姆浅:玫姆绞剑脩魬B(tài)應(yīng)用使用標(biāo)準(zhǔn)的 socket API 就可以使用 netlink 提供的強(qiáng)大功能,
    內(nèi)核態(tài)需要使用專門的內(nèi)核 API 來使用 netlink。
    Netlink 相對于系統(tǒng)調(diào)用ioctl 以及 /proc文件系統(tǒng)而言具有以下優(yōu)點(diǎn):
    1,netlink使用簡單,只需要在include/linux/netlink.h中增加一個新類型的 netlink 協(xié)議定義即可,(如 #define NETLINK_TEST 20 然后,內(nèi)核和用戶態(tài)應(yīng)用就可以立即通過 socket API 使用該 netlink 協(xié)議類型進(jìn)行數(shù)據(jù)交換);
    2. netlink是一種異步通信機(jī)制,在內(nèi)核與用戶態(tài)應(yīng)用之間傳遞的消息保存在socket緩存隊(duì)列中,發(fā)送消息只是把消息保存在接收者的socket的接收隊(duì)列,而不需要等待接收者收到消息;
    3.使用 netlink 的內(nèi)核部分可以采用模塊的方式實(shí)現(xiàn),使用 netlink 的應(yīng)用部分和內(nèi)核部分沒有編譯時依賴;
    4.netlink 支持多播,內(nèi)核模塊或應(yīng)用可以把消息多播給一個netlink組,屬于該neilink 組的任何內(nèi)核模塊或應(yīng)用都能接收到該消息,內(nèi)核事件向用戶態(tài)的通知機(jī)制就使用了這一特性;
    5.內(nèi)核可以使用 netlink 首先發(fā)起會話;

二、Netlink常用數(shù)據(jù)結(jié)構(gòu)及函數(shù)

 用戶態(tài)應(yīng)用使用標(biāo)準(zhǔn)的 socket API有(sendto()),recvfrom(); sendmsg(), recvmsg())

 下面簡單介紹幾種NETLINK用戶態(tài)通信的常用數(shù)據(jù)結(jié)構(gòu)

 1、用戶態(tài)數(shù)據(jù)結(jié)構(gòu)

   Netlink通信跟常用UDP Socket通信類似:
 struct sockaddr_nl 是netlink通信地址跟普通socket struct sockaddr_in類似
  struct sockaddr_nl結(jié)構(gòu): 

1 struct sockaddr_nl {2     __kernel_sa_family_t    nl_family;  /* AF_NETLINK (跟AF_INET對應(yīng))*/3     unsigned short  nl_pad;     /* zero */4     __u32       nl_pid;     /* port ID  (通信端口號)*/5     __u32       nl_groups;  /* multicast groups mask */6 };

struct nlmsghd 結(jié)構(gòu):

1 /* struct nlmsghd 是netlink消息頭*/2 struct nlmsghdr {   3     __u32       nlmsg_len;  /* Length of message including header */4     __u16       nlmsg_type; /* Message content */5     __u16       nlmsg_flags;    /* Additional flags */ 6     __u32       nlmsg_seq;  /* Sequence number */7     __u32       nlmsg_pid;  /* Sending process port ID */8 };

(1)nlmsg_len:整個netlink消息的長度(包含消息頭);
(2)nlmsg_type:消息狀態(tài),內(nèi)核在include/uapi/linux/netlink.h中定義了以下4種通用的消息類型,它們分別是:

 1 #define NLMSG_NOOP      0x1 /* Nothing.     */ 2 #define NLMSG_ERROR     0x2 /* Error        */ 3 #define NLMSG_DONE      0x3 /* End of a dump    */ 4 #define NLMSG_OVERRUN       0x4 /* Data lost        */ 5  6 #define NLMSG_MIN_TYPE      0x10    /* < 0x10: reserved control messages */ 7  8 /*NLMSG_NOOP:不執(zhí)行任何動作,必須將該消息丟棄; 9 NLMSG_ERROR:消息發(fā)生錯誤;10 NLMSG_DONE:標(biāo)識分組消息的末尾;11 NLMSG_OVERRUN:緩沖區(qū)溢出,表示某些消息已經(jīng)丟失。12 NLMSG_MIN_TYPEK:預(yù)留 */

(3)nlmsg_flags:消息標(biāo)記,它們用以表示消息的類型,如下

 1 /* Flags values */ 2  3 #define NLM_F_REQUEST       1   /* It is request message.   */ 4 #define NLM_F_MULTI     2   /* Multipart message, terminated by NLMSG_DONE */ 5 #define NLM_F_ACK       4   /* Reply with ack, with zero or error code */ 6 #define NLM_F_ECHO      8   /* Echo this request        */ 7 #define NLM_F_DUMP_INTR     16  /* Dump was inconsistent due to sequence change */ 8  9 /* Modifiers to GET request */10 #define NLM_F_ROOT  0x100   /* specify tree root    */11 #define NLM_F_MATCH 0x200   /* return all matching  */12 #define NLM_F_ATOMIC    0x400   /* atomic GET       */13 #define NLM_F_DUMP  (NLM_F_ROOT|NLM_F_MATCH)14 15 /* Modifiers to NEW request */16 #define NLM_F_REPLACE   0x100   /* Override existing        */17 #define NLM_F_EXCL  0x200   /* Do not touch, if it exists   */18 #define NLM_F_CREATE    0x400   /* Create, if it does not exist */19 #define NLM_F_APPEND    0x800   /* Add to end of list       */

(4)nlmsg_seq:消息序列號,用以將消息排隊(duì),有些類似TCP協(xié)議中的序號(不完全一樣),但是netlink的這個字段是可選的,不強(qiáng)制使用;
(5)nlmsg_pid:發(fā)送端口的ID號,對于內(nèi)核來說該值就是0,對于用戶進(jìn)程來說就是其socket所綁定的ID號。

struct msghdr 結(jié)構(gòu)體

 1 struct iovec {                    /* Scatter/gather array items */ 2      void  *iov_base;              /* Starting address */ 3      size_t iov_len;               /* Number of bytes to transfer */ 4  }; 5   /* iov_base: iov_base指向數(shù)據(jù)包緩沖區(qū),即參數(shù)buff,iov_len是buff的長度。msghdr中允許一次傳遞多個buff, 6     以數(shù)組的形式組織在 msg_iov中,msg_iovlen就記錄數(shù)組的長度 (即有多少個buff) 7   */ 8  struct msghdr { 9      void         *msg_name;       /* optional address */10      socklen_t     msg_namelen;    /* size of address */11      struct iovec *msg_iov;        /* scatter/gather array */12      size_t        msg_iovlen;     /* # elements in msg_iov */13      void         *msg_control;    /* ancillary data, see below */14      size_t        msg_controllen; /* ancillary data buffer len */15      int           msg_flags;      /* flags on received message */16  };17  /* msg_name: 數(shù)據(jù)的目的地址,網(wǎng)絡(luò)包指向sockaddr_in, netlink則指向sockaddr_nl;18     msg_namelen: msg_name 所代表的地址長度19     msg_iov: 指向的是緩沖區(qū)數(shù)組20     msg_iovlen: 緩沖區(qū)數(shù)組長度21     msg_control: 輔助數(shù)據(jù),控制信息(發(fā)送任何的控制信息)22     msg_controllen: 輔助信息長度23     msg_flags: 消息標(biāo)識24  */

 2. netlink 內(nèi)核數(shù)據(jù)結(jié)構(gòu)、常用宏及函數(shù):

netlink消息類型:

 1 #define NETLINK_ROUTE       0   /* Routing/device hook              */ 2 #define NETLINK_UNUSED      1   /* Unused number                */ 3 #define NETLINK_USERSOCK    2   /* Reserved for user mode socket protocols  */ 4 #define NETLINK_FIREWALL    3   /* Unused number, formerly ip_queue     */ 5 #define NETLINK_SOCK_DIAG   4   /* socket monitoring                */ 6 #define NETLINK_NFLOG       5   /* netfilter/iptables ULOG */ 7 #define NETLINK_XFRM        6   /* ipsec */ 8 #define NETLINK_SELINUX     7   /* SELinux event notifications */ 9 #define NETLINK_ISCSI       8   /* Open-iSCSI */10 #define NETLINK_AUDIT       9   /* auditing */11 #define NETLINK_FIB_LOOKUP  10  12 #define NETLINK_CONNECTOR   1113 #define NETLINK_NETFILTER   12  /* netfilter subsystem */14 #define NETLINK_IP6_FW      1315 #define NETLINK_DNRTMSG     14  /* DECnet routing messages */16 #define NETLINK_KOBJECT_UEVENT  15  /* Kernel messages to userspace */17 #define NETLINK_GENERIC     1618 /* leave room for NETLINK_DM (DM Events) */19 #define NETLINK_SCSITRANSPORT   18  /* SCSI Transports */20 #define NETLINK_ECRYPTFS    1921 #define NETLINK_RDMA        2022 #define NETLINK_CRYPTO      21  /* Crypto layer */23 24 #define NETLINK_INET_DIAG   NETLINK_SOCK_DIAG25 26 #define MAX_LINKS 32 

netlink常用宏

 1 #define NLMSG_ALIGNTO   4U 2 /* 宏NLMSG_ALIGN(len)用于得到不小于len且字節(jié)對齊的最小數(shù)值 */ 3 #define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) ) 4  5 /* Netlink 頭部長度 */ 6 #define NLMSG_HDRLEN     ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr))) 7  8 /* 計(jì)算消息數(shù)據(jù)len的真實(shí)消息長度(消息體 + 消息頭)*/ 9 #define NLMSG_LENGTH(len) ((len) + NLMSG_HDRLEN)10 11 /* 宏NLMSG_SPACE(len)返回不小于NLMSG_LENGTH(len)且字節(jié)對齊的最小數(shù)值 */12 #define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len))13 14 /* 宏NLMSG_DATA(nlh)用于取得消息的數(shù)據(jù)部分的首地址,設(shè)置和讀取消息數(shù)據(jù)部分時需要使用該宏 */15 #define NLMSG_DATA(nlh)  ((void*)(((char*)nlh) + NLMSG_LENGTH(0)))16 17 /* 宏NLMSG_NEXT(nlh,len)用于得到下一個消息的首地址, 同時len 變?yōu)槭S嘞⒌拈L度 */18 #define NLMSG_NEXT(nlh,len)  ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), 19                   (struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))20 21 /* 判斷消息是否 >len */22 #define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && 23                (nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && 24                (nlh)->nlmsg_len <= (len))25 26 /* NLMSG_PAYLOAD(nlh,len) 用于返回payload的長度*/27 #define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len)))

netlink 內(nèi)核常用函數(shù):

netlink_kernel_create內(nèi)核函數(shù)用于創(chuàng)建 內(nèi)核socket用用戶態(tài)通信 

 1 static inline struct sock * 2 netlink_kernel_create(struct net *net, int unit, struct netlink_kernel_cfg *cfg) 3 /* net: net指向所在的網(wǎng)絡(luò)命名空間, 一般默認(rèn)傳入的是&init_net(不需要定義);  定義在net_namespace.c(extern struct net init_net); 4    unit:netlink協(xié)議類型 5    cfg: cfg存放的是netlink內(nèi)核配置參數(shù)(如下) 6 */ 7  8 /* optional Netlink kernel configuration parameters */ 9 struct netlink_kernel_cfg {10     unsigned int    groups;  11     unsigned int    flags;  12     void        (*input)(struct sk_buff *skb); /* input 回調(diào)函數(shù) */13     struct mutex    *cb_mutex; 14     void        (*bind)(int group); 15     bool        (*compare)(struct net *net, struct sock *sk);16 };

 單播netlink_unicast() 和 多播netlink_broadcast()

 1 /* 來發(fā)送單播消息 */ 2 extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 portid, int nonblock); 3 /* ssk: netlink socket  4    skb: skb buff 指針 5    portid: 通信的端口號 6    nonblock:表示該函數(shù)是否為非阻塞,如果為1,該函數(shù)將在沒有接收緩存可利用時立即返回,而如果為0,該函數(shù)在沒有接收緩存可利用 定時睡眠 7 */ 8  9 /* 用來發(fā)送多播消息 */10 extern int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, __u32 portid,11                  __u32 group, gfp_t allocation);12 /* ssk: 同上(對應(yīng)netlink_kernel_create 返回值)、13    skb: 內(nèi)核skb buff14    portid: 端口id15    group: 是所有目標(biāo)多播組對應(yīng)掩碼的"OR"操作的合值。16    allocation: 指定內(nèi)核內(nèi)存分配方式,通常GFP_ATOMIC用于中斷上下文,而GFP_KERNEL用于其他場合。17                 這個參數(shù)的存在是因?yàn)樵揂PI可能需要分配一個或多個緩沖區(qū)來對多播消息進(jìn)行clone18 */

 三、netlink實(shí)例
(1)用戶態(tài)程序 (sendto(), recvfrom())

 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <sys/socket.h> 4 #include <string.h> 5 #include <linux/netlink.h> 6 #include <stdint.h> 7 #include <unistd.h> 8 #include <errno.h> 9 10 #define NETLINK_TEST    3011 #define MSG_LEN            12512 #define MAX_PLOAD        12513 14 typedef struct _user_msg_info15 {16     struct nlmsghdr hdr;17     char  msg[MSG_LEN];18 } user_msg_info;19 20 int main(int argc, char **argv)21 {22     int skfd;23     int ret;24     user_msg_info u_info;25     socklen_t len;26     struct nlmsghdr *nlh = NULL;27     struct sockaddr_nl saddr, daddr;28     char *umsg = "hello netlink!!";29 30     /* 創(chuàng)建NETLINK socket */31     skfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_TEST);32     if(skfd == -1)33     {34         perror("create socket error\n");35         return -1;36     }37 38     memset(&saddr, 0, sizeof(saddr));39     saddr.nl_family = AF_NETLINK; //AF_NETLINK40     saddr.nl_pid = 100;  //端口號(port ID) 41     saddr.nl_groups = 0;42     if(bind(skfd, (struct sockaddr *)&saddr, sizeof(saddr)) != 0)43     {44         perror("bind() error\n");45         close(skfd);46         return -1;47     }48 49     memset(&daddr, 0, sizeof(daddr));50     daddr.nl_family = AF_NETLINK;51     daddr.nl_pid = 0; // to kernel 52     daddr.nl_groups = 0;53 54     nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PLOAD));55     memset(nlh, 0, sizeof(struct nlmsghdr));56     nlh->nlmsg_len = NLMSG_SPACE(MAX_PLOAD);57     nlh->nlmsg_flags = 0;58     nlh->nlmsg_type = 0;59     nlh->nlmsg_seq = 0;60     nlh->nlmsg_pid = saddr.nl_pid; //self port61 62     memcpy(NLMSG_DATA(nlh), umsg, strlen(umsg));63     ret = sendto(skfd, nlh, nlh->nlmsg_len, 0, (struct sockaddr *)&daddr, sizeof(struct sockaddr_nl));64     if(!ret)65     {66         perror("sendto error\n");67         close(skfd);68         exit(-1);69     }70     printf("send kernel:%s\n", umsg);71 72     memset(&u_info, 0, sizeof(u_info));73     len = sizeof(struct sockaddr_nl);74     ret = recvfrom(skfd, &u_info, sizeof(user_msg_info), 0, (struct sockaddr *)&daddr, &len);75     if(!ret)76     {77         perror("recv form kernel error\n");78         close(skfd);79         exit(-1);80     }81 82     printf("from kernel:%s\n", u_info.msg);83     close(skfd);84 85     free((void *)nlh);86     return 0;87 }

Netlink 內(nèi)核模塊代碼:

  1 /****************************************  2 * Author: zhangwj  3 * Date: 2017-01-19  4 * Filename: netlink_test.c  5 * Descript: netlink of kernel  6 * Kernel: 3.10.0-327.22.2.el7.x86_64  7 * Warning:  8 ******************************************/  9  10 #include <linux/init.h> 11 #include <linux/module.h> 12 #include <linux/types.h> 13 #include <net/sock.h> 14 #include <linux/netlink.h> 15  16 #define NETLINK_TEST     30 17 #define MSG_LEN            125 18 #define USER_PORT        100 19  20 MODULE_LICENSE("GPL"); 21 MODULE_AUTHOR("zhangwj"); 22 MODULE_DESCRIPTION("netlink example"); 23  24 struct sock *nlsk = NULL; 25 extern struct net init_net; 26  27 int send_usrmsg(char *pbuf, uint16_t len) 28 { 29     struct sk_buff *nl_skb; 30     struct nlmsghdr *nlh; 31  32     int ret; 33  34     /* 創(chuàng)建sk_buff 空間 */ 35     nl_skb = nlmsg_new(len, GFP_ATOMIC); 36     if(!nl_skb) 37     { 38         printk("netlink alloc failure\n"); 39         return -1; 40     } 41  42     /* 設(shè)置netlink消息頭部 */ 43     nlh = nlmsg_put(nl_skb, 0, 0, NETLINK_TEST, len, 0); 44     if(nlh == NULL) 45     { 46         printk("nlmsg_put failaure \n"); 47         nlmsg_free(nl_skb); 48         return -1; 49     } 50  51     /* 拷貝數(shù)據(jù)發(fā)送 */ 52     memcpy(nlmsg_data(nlh), pbuf, len); 53     ret = netlink_unicast(nlsk, nl_skb, USER_PORT, MSG_DONTWAIT); 54  55     return ret; 56 } 57  58 static void netlink_rcv_msg(struct sk_buff *skb) 59 { 60     struct nlmsghdr *nlh = NULL; 61     char *umsg = NULL; 62     char *kmsg = "hello users!!!"; 63  64     if(skb->len >= nlmsg_total_size(0)) 65     { 66         nlh = nlmsg_hdr(skb); 67         umsg = NLMSG_DATA(nlh); 68         if(umsg) 69         { 70             printk("kernel recv from user: %s\n", umsg); 71             send_usrmsg(kmsg, strlen(kmsg)); 72         } 73     } 74 } 75  76 struct netlink_kernel_cfg cfg = {  77         .input  = netlink_rcv_msg, /* set recv callback */ 78 };   79  80 int test_netlink_init(void) 81 { 82     /* create netlink socket */ 83     nlsk = (struct sock *)netlink_kernel_create(&init_net, NETLINK_TEST, &cfg); 84     if(nlsk == NULL) 85     {    86         printk("netlink_kernel_create error !\n"); 87         return -1;  88     }    89     printk("test_netlink_init\n"); 90      91     return 0; 92 } 93  94 void test_netlink_exit(void) 95 { 96     if (nlsk){ 97         netlink_kernel_release(nlsk); /* release ..*/ 98         nlsk = NULL; 99     }   100     printk("test_netlink_exit!\n");101 }102 103 module_init(test_netlink_init);104 module_exit(test_netlink_exit);

Makeflie:

 1 # 2 #Desgin of Netlink 3 # 4  5 MODULE_NAME :=netlink_test 6 obj-m :=$(MODULE_NAME).o 7  8 KERNELDIR ?= /lib/modules/$(shell uname -r)/build 9 PWD := $(shell pwd)10 11 all:12     $(MAKE) -C $(KERNELDIR) M=$(PWD)13 14 clean:15     $(MAKE) -C $(KERNELDIR) M=$(PWD) clean

運(yùn)行結(jié)果:

首先將編譯出來的Netlink內(nèi)核模塊插入到系統(tǒng)當(dāng)中(insmod netlink_test.ko)可以看到如下:

1 [root@localhost nt_2nd]# insmod netlink_test.ko 2 [root@localhost nt_2nd]# dmesg3 [25024.276345] test_netlink_init

接著運(yùn)行應(yīng)用程序:./a.out

1 [root@localhost nt_2nd]# ./a.out 2 send kernel:hello netlink!!3 from kernel:hello users!!!4 [root@localhost nt_2nd]# dmesg 5 [25024.276345] test_netlink_init6 [25117.548350] kernel recv from user: hello netlink!!7 [root@localhost nt_2nd]# 

 

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
linux 內(nèi)核和用戶空間通信之netlink使用方法
Linux 內(nèi)核態(tài)與用戶態(tài)通信 netlink
用戶空間和內(nèi)核空間通訊之Netlink
通過netlink實(shí)現(xiàn)內(nèi)核模塊和應(yīng)用層通信
用戶空間和內(nèi)核空間通訊之【Netlink 下】
netlink socket 編程之 why & how - 內(nèi)核源碼 - ChinaUn...
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服