Linux Netlink 实例:演示如何使用 Netlink 进行进程间通信 (linux netlink 实例)

在 Linux 操作系统中,进程间通信是很常见的需求。在 Linux 内核中,可以用 Netlink 协议来进行进程间通信,Netlink 是一种内核与用户空间之间的通信机制,常常被用来在用户空间和内核空间进行通信。本篇文章将演示如何使用 Netlink 协议来进行进程间通信。在开始之前,我们需要先了解一下 Netlink 协议。

Netlink 是 Linux 内部用来通信的一种原始协议,用于内核与用户空间的通信,包括进程间通信和用户态网络协议栈通信等。Netlink 主要通过数据报套接字进行通信,可以将数据从用户空间发送到内核空间,反之亦然。每个 Netlink 套接字都有一个唯一的标识符,用来标识通信进程。

具体来说,在内核中,Netlink 主要包括三个方面:Netlink 套接字、Netlink 协议和 Netlink 属性。Netlink 套接字指的是 Linux 内核中在通信过程中使用的套接字,可以用它来发送和接收 Netlink 消息。Netlink 协议指的是在 Netlink 消息中使用的一些特定的协议,用来标识消息的类型和属性。Netlink 属性指的是在 Netlink 消息中使用的一些可变的属性,用来传递消息的具体内容。

下面,我们将演示一个 Netlink 使用的示例,通过该示例,你可以了解到如何使用 Netlink 进行进程间通信。

我们需要在用户空间中创建一个 Netlink 套接字,这个套接字用来向内核发送消息,并接收内核返回的消息。在 Linux 操作系统中,可以使用 socket 系统调用来创建一个 Netlink 套接字。

“`c

int skfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);

if(skfd

printf(“Fled to create socket\n”);

return -1;

}

“`

上述代码创建了一个 Netlink 套接字,该套接字使用 NETLINK_GENERIC 协议,可以用来发送和接收各种类型的消息。如果创建成功,socket 函数返回一个套接字描述符,否则返回 -1。

接下来,我们需要将 Netlink 套接字绑定到本地地址上,以便能够接收内核发送的消息。在 Netlink 中,使用 sockaddr_nl 结构体来表示 Netlink 套接字的地址。在绑定套接字的时候,需要使用 bind 系统调用,并设置 sockaddr_nl 结构体中的 nl_family、 nl_pad 和 nl_pid 字段。

“`c

struct sockaddr_nl sa;

memset(&sa, 0, sizeof(sa));

sa.nl_family = AF_NETLINK;

sa.nl_pid = getpid();

bind(skfd, (struct sockaddr *)&sa, sizeof(sa));

“`

上述代码将 Netlink 套接字绑定到本地地址上,并设置了 nl_pid 字段为当前进程的进程 ID。这样,我们就可以从内核接收消息了。

在 Netlink 中,使用 netlink_kernel_create 函数来创建一个 Netlink 协议,该协议可以用来发送和接收消息。这个函数定义如下:

“`c

struct netlink_kernel_cfg cfg = {

.input = nl_recv_msg,

};

struct netlink_kernel_cfg cfg = {

.input = nl_recv_msg,

};

netlink_kernel_create(&init_net, NETLINK_TEST, &cfg);

“`

上述代码使用 netlink_kernel_create 函数创建了一个类型为 NETLINK_TEST 的 Netlink 协议,该协议的输入处理函数为 nl_recv_msg。在接收到消息时,内核会将该消息传递给 nl_recv_msg 函数进行处理。

接下来,我们可以使用 sendmsg 系统调用向内核发送消息,在 Netlink 中,使用 nlmsghdr 结构体来表示 Netlink 消息头部。下面是一个典型的 Netlink 消息的结构:

“`c

struct nlmsghdr {

__u32 nlmsg_len; // 消息的长度,包括头部和负载数据

__u16 nlmsg_type; // 消息的类型

__u16 nlmsg_flags; // 消息的标志

__u32 nlmsg_seq; // 序列号

__u32 nlmsg_pid; // 进程 ID

};

“`

在发送消息的时候,我们需要填充这个结构体,并将消息长度设置为 nlmsg_len 加上负载数据的长度。下面是一个示例代码:

“`c

struct nlmsghdr *msg;

struct iovec iov;

struct msghdr mh;

msg = (struct nlmsghdr *) malloc(NLMSG_SPACE(MAX_PAYLOAD));

memset(msg, 0, NLMSG_SPACE(MAX_PAYLOAD));

msg->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);

msg->nlmsg_flags = NLM_F_REQUEST;

msg->nlmsg_type = MSG_TYPE;

iov.iov_base = (void *) msg;

iov.iov_len = msg->nlmsg_len;

mh.msg_name = (void *)&sa;

mh.msg_namelen = sizeof(sa);

mh.msg_iov = &iov;

mh.msg_iovlen = 1;

sendmsg(skfd, &mh, 0);

“`

上述代码创建了一个类型为 MSG_TYPE 的 Netlink 消息,并使用 sendmsg 函数将其发送到内核。在发送消息时,我们需要将 Netlink 消息体放到缓冲区中,并将其作为 iovec 结构体的 iov_base 成员传递给 sendmsg 函数。

在接收到消息之后,内核会调用我们指定的输入处理函数进行处理。在这个处理函数中,我们可以打印出接收到的消息。

“`c

void nl_recv_msg(struct sk_buff *skb) {

struct nlmsghdr *nlh = (struct nlmsghdr *)skb->data;

int pid = nlh->nlmsg_pid;

printf(“Received message from kernel\n”);

while (NLMSG_OK(nlh, skb->len)) {

printf(“Message: %s\n”, NLMSG_DATA(nlh));

nlh = NLMSG_NEXT(nlh, skb->len);

}

}

“`

上述代码使用了 NLMSG_OK 和 NLMSG_NEXT 宏来遍历接收到的消息,打印出消息的内容。在处理完消息之后,我们需要发送一个回复消息给内核,以确认收到了内核的消息。在 Netlink 中,使用 rtnetlink_broadcast 函数来发送回复消息。

“`c

struct sk_buff *msg;

struct nlmsghdr *nlh;

msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);

nlh = nlmsg_put(msg, 0, 0, 0, NLMSG_ALIGN(NLMSG_LENGTH(len)), 0);

NETLINK_CB(msg).dst_group = 0;

strcpy(NLMSG_DATA(nlh), “This is a response message from user space.”);

nlmsg_multicast(nl_sk, skb, 0, MYGRP, GFP_KERNEL);

“`

上述代码创建了一个回复消息,并使用 nlmsg_multicast 函数将其发送给内核。在这里,我们设置了要发送的消息组为 MYGRP,内核会将该组的所有消息都发送回来。

到此为止,我们已经演示了如何使用 Netlink 协议进行进程间通信的示例。通过本文的演示,你可以了解到 Netlink 在 Linux 内核中的使用方法,希望对你有所帮助。

相关问题拓展阅读:

在新的linux内核实现热插拔是通过netlink的方式,不过为什么uevent通过netlink发送不出去呀,求真理!!

热插是通过 硬盘NCQ 技术的 和操作系统没关系 你完全搞错概念了

netlink更大传输字节

netlink最握帆芦大传输字节是18个字节。

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 更加混乱。

2. netlink是一种异步通信机制,在内核与用户态应用之间传递的消息保存在socket缓存队列中,发送消息只是把消息保存在接收者的socket的接收队列,而不需要等待接收者收到消息,但系统调用与 ioctl 则是同步通信机制,如果传递的数据太长,将影响调度粒度。

3.使用 netlink 的内核部分可以采用模块的方式实现,使用 netlink 的应用部分和内核部分没有编译时依赖,但系统调用就有依赖,而且新的系统调用的实现必须静态地连接到内核中,它无法在模块中实现,使用新系统调用的应用在编译时需要依赖内核。

4.netlink 支持多播,内核模块或应用可以把消息多播给一个netlink组,属于该neilink 组的任何内核模块或应用都能接收到该消息,内核事件向用户态的通知机制就使用了这一特性,任何对内核事件感兴趣的应用都能收到该子系统发送的内核事件,在后面的文章中将介绍这一机制的使用。

5.内核可以使用 netlink 首先发起会话,但系统调用和 ioctl 只能由用轿雹户应用发起调用。

6.netlink 使用标准的 socket API,因此很容易使用,但系统调用和 ioctl则需要专门的培训才能使用。

linux netlink 实例的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于linux netlink 实例,Linux Netlink 实例:演示如何使用 Netlink 进行进程间通信,在新的linux内核实现热插拔是通过netlink的方式,不过为什么uevent通过netlink发送不出去呀,求真理!!,netlink更大传输字节的信息别忘了在本站进行查找喔。


数据运维技术 » Linux Netlink 实例:演示如何使用 Netlink 进行进程间通信 (linux netlink 实例)