日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux 内核态与用户态通信 netlink

發布時間:2023/12/18 linux 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux 内核态与用户态通信 netlink 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

參考資料:

https://blog.csdn.net/zqixiao_09/article/details/77131283

https://www.cnblogs.com/lopnor/p/6158800.html

?

?

?

?

?

Netlink 是一種特殊的 socket,它是 Linux 所特有的,類似于 BSD 中的AF_ROUTE 但又遠比它的功能強大,目前在最新的 Linux 內核(2.6.14)中使用netlink 進行應用與內核通信的應用很多,包括:路由 daemon(NETLINK_ROUTE),1-wire 子系統(NETLINK_W1),用戶態 socket 協議(NETLINK_USERSOCK),防火墻(NETLINK_FIREWALL),socket 監視(NETLINK_INET_DIAG),netfilter 日志(NETLINK_NFLOG),ipsec 安全策略(NETLINK_XFRM),SELinux 事件通知(NETLINK_SELINUX),iSCSI 子系統(NETLINK_ISCSI),進程審計(NETLINK_AUDIT),轉發信息表查詢(NETLINK_FIB_LOOKUP),netlink connector(NETLINK_CONNECTOR),netfilter 子系統(NETLINK_NETFILTER),IPv6 防火墻(NETLINK_IP6_FW),DECnet 路由信息(NETLINK_DNRTMSG),內核事件向用戶態通知(NETLINK_KOBJECT_UEVENT),通用 netlink(NETLINK_GENERIC)。

Netlink 是一種在內核與用戶應用間進行雙向數據傳輸的非常好的方式,用戶態應用使用標準的 socket API 就可以使用 netlink 提供的強大功能,內核態需要使用專門的內核 API 來使用 netlink。

Netlink 相對于系統調用,ioctl 以及 /proc 文件系統而言具有以下優點:

1,為了使用 netlink,用戶僅需要在 include/linux/netlink.h 中增加一個新類型的 netlink 協議定義即可, 如 #define NETLINK_MYTEST 17 然后,內核和用戶態應用就可以立即通過 socket API 使用該 netlink 協議類型進行數據交換。但系統調用需要增加新的系統調用,ioctl 則需要增加設備或文件, 那需要不少代碼,proc 文件系統則需要在 /proc 下添加新的文件或目錄,那將使本來就混亂的 /proc 更加混亂。

問題:

增加了netlink協議后,需要重新編譯內核嗎?還是僅僅修改了頭文件netlink.h就可以了呢?在后期的實驗中,需要對這一問題進行驗證。

2. netlink是一種異步通信機制,在內核與用戶態應用之間傳遞的消息保存在socket緩存隊列中,發送消息只是把消息保存在接收者的socket的接收隊列,而不需要等待接收者收到消息,但系統調用與 ioctl 則是同步通信機制,如果傳遞的數據太長,將影響調度粒度。

異步通信與同步通信的區別:看接受者的響應方式。異步通訊是不需要接受者立即響應的

3.使用 netlink 的內核部分可以采用模塊的方式實現,使用 netlink 的應用部分和內核部分沒有編譯時依賴,但系統調用就有依賴,而且新的系統調用的實現必須靜態地連接到內核中,它無法在模塊中實現,使用新系統調用的應用在編譯時需要依賴內核。

可以像編寫驅動模塊一樣的實現方式來實現netlink部分。

4.netlink 支持多播,內核模塊或應用可以把消息多播給一個netlink組,屬于該neilink 組的任何內核模塊或應用都能接收到該消息,內核事件向用戶態的通知機制就使用了這一特性,任何對內核事件感興趣的應用都能收到該子系統發送的內核事件,在后面的文章中將介紹這一機制的使用。

5.內核可以使用 netlink 首先發起會話,但系統調用和 ioctl 只能由用戶應用發起調用。

內核主動向用戶應用發起數據

6.netlink 使用標準的 socket API,因此很容易使用,但系統調用和 ioctl則需要專門的培訓才能使用。

?

NETLINK_GENERIC是一個通用的協議類型,它是專門為用戶使用的,因此,用戶可以直接使用它,而不必再添加新的協議類型。

?

#include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/types.h> #include <linux/sched.h> #include <net/sock.h> #include <net/netlink.h> #include <linux/netlink.h>#define NETLINK_USER 22 #define USER_MSG (NETLINK_USER + 1) #define USER_PORT 50  /*此處是寫死了,可以用進程ID,表示來自用戶態的唯一進程*/MODULE_LICENSE("GPL"); MODULE_AUTHOR("arvik"); MODULE_DESCRIPTION("netlink_demo");static void test_netlink_rcv(struct sk_buff *skb);struct netlink_kernel_cfg cfg = {.input = test_netlink_rcv,/*...*/ }; static struct sock *test_netlink_sock = NULL;int send_msg(int8_t *pbuf, uint16_t len) {struct sk_buff *nl_skb;struct nlmsghdr *nlh;int ret;nl_skb = nlmsg_new(len, GFP_ATOMIC);if (!nl_skb) {printk("netlink_alloc_skb error\n");return -1;}/*將header填充到skb中*/nlh = nlmsg_put(nl_skb, 0, 0, USER_MSG, len, 0);if (nlh == NULL) {printk("put error\n");nlmsg_free(nl_skb);return -1;}/*拷貝data*/memcpy(nlmsg_data(nlh), pbuf, len);/*發送*/ret = netlink_unicast(test_netlink_sock, nl_skb, USER_PORT, MSG_DONTWAIT);return ret; }static void test_netlink_rcv(struct sk_buff *skb) {struct nlmsghdr *nlh = NULL;void *data = NULL;printk("skb->len %u\n", skb->len);if (skb->len >= nlmsg_total_size(0)){nlh = nlmsg_hdr(skb);data = NLMSG_DATA(nlh);if (data) {printk("kernel receive date : %s\n", (int8_t *)data);send_msg(data, nlmsg_len(nlh));}} }static int __init test_netlink_init(void) {printk("test netlink init\n");test_netlink_sock = netlink_kernel_create(&init_net, USER_MSG, &cfg); if (test_netlink_sock == NULL) {printk("test netlink init error\n");return -1;}printk("test netlink init ok\n");return 0; } static void __exit test_netlink_exit(void) {netlink_kernel_release(test_netlink_sock);test_netlink_sock = NULL;printk("test netlink exit\n"); }module_init(test_netlink_init); module_exit(test_netlink_exit);

?

?

#include <stdio.h> #include <stdlib.h> #include <sys/socket.h> #include <string.h> #include <linux/netlink.h> #include <stdint.h> #include <unistd.h> #include <errno.h>#define NETLINK_USER 22 #define USER_MSG (NETLINK_USER + 1)#define MSG_LEN 100#define MAX_PLOAD 100struct _my_msg {struct nlmsghdr hdr;int8_t data[MSG_LEN]; };int main() {char *data = "hello kernel";socklen_t addr_len;struct sockaddr_nl local, dest_addr;int skfd;struct nlmsghdr *nlh = NULL;struct _my_msg info;int ret;//創建socketskfd = socket(AF_NETLINK, SOCK_RAW, USER_MSG);if (skfd == (-1)) {fprintf(stderr, "create socket error...%s\n", strerror(errno));return (-1);}/*綁定*/memset(&local, 0, sizeof(local));local.nl_family = AF_NETLINK;local.nl_pid = 50;  /*此處的pid通常用進程ID,表示來自用戶態的唯一進程*/local.nl_groups = 0;if (bind(skfd, (struct sockaddr *)&local, sizeof(local)) != 0) {fprintf(stderr, "bind error\n");close(skfd);return (-1);}//初始化目的地址memset(&dest_addr, 0, sizeof(dest_addr));dest_addr.nl_family = AF_NETLINK; dest_addr.nl_pid = 0;dest_addr.nl_groups = 0;/*填寫data*/nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PLOAD));memset(nlh, 0, sizeof(struct nlmsghdr));nlh->nlmsg_len = NLMSG_SPACE(MAX_PLOAD);nlh->nlmsg_flags = 0;nlh->nlmsg_type = 0;nlh->nlmsg_seq = 0;nlh->nlmsg_pid = local.nl_pid;memcpy(NLMSG_DATA(nlh), data, strlen(data));ret = sendto(skfd, nlh, nlh->nlmsg_len, 0, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr_nl));if (ret < 0) { // fprintf(stderr, "sendto error\n");perror("sendto error: ");close(skfd);return (-1);}printf("wait kernel msg!\n");memset(&info, 0, sizeof(info));/*接受信息*/ret = recvfrom(skfd, &info, sizeof(struct _my_msg), 0, (struct sockaddr *)&dest_addr, &addr_len);if (ret <= 0) { // fprintf(stderr, "recv from kernel error\n");perror("recv from kernel error: ");close(skfd);return (-1);}printf("msg receive from kernel : %s\n", info.data);close(skfd);free((void *)nlh);close(skfd);return 0; }

?

轉載于:https://www.cnblogs.com/rivsidn/p/10493954.html

總結

以上是生活随笔為你收集整理的Linux 内核态与用户态通信 netlink的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。