当前位置: 首页 > wzjs >正文

网站建设的服务怎么样seo研究中心论坛

网站建设的服务怎么样,seo研究中心论坛,湖北网站定制开发价格表,代做毕网站一、基础知识 Netlink 是 Linux 系统中一种内核与用户空间通信的高效机制,而 Netlink 消息是这种通信的核心载体。它允许用户态程序(如网络配置工具、监控工具)与内核子系统(如网络协议栈、设备驱动)交换数据&#xff…

一、基础知识

        Netlink 是 Linux 系统中一种内核与用户空间通信的高效机制,而 Netlink 消息是这种通信的核心载体。它允许用户态程序(如网络配置工具、监控工具)与内核子系统(如网络协议栈、设备驱动)交换数据,例如获取网络接口信息、配置路由表、接收内核事件通知等。


Netlink 消息的组成

一个完整的 Netlink 消息由两部分构成:

  1. 消息头(struct nlmsghdr
    定义消息的元信息,例如消息类型、长度、序列号等。

    struct nlmsghdr {__u32 nlmsg_len;    // 消息总长度(头部 + 数据)__u16 nlmsg_type;   // 消息类型(如请求、响应、错误)__u16 nlmsg_flags;  // 标志位(如请求标志、多部分消息标志)__u32 nlmsg_seq;    // 序列号(用于匹配请求和响应)__u32 nlmsg_pid;    // 发送方端口ID(通常为进程ID)
    };
  2. 消息体(Payload)
    具体的数据内容,格式由消息类型决定。例如:

    • 路由消息:struct rtgenmsg(指定地址族)

    • 接口信息:struct ifinfomsg(接口索引、状态等)

    • 属性列表:动态附加的属性(如接口名称、MAC地址等)。


Netlink 消息的作用

Netlink 消息的核心功能是双向通信

1. 用户空间 → 内核

用户程序通过发送 Netlink 消息向内核发起操作请求。例如:

  • 查询信息RTM_GETLINK(获取网络接口列表)、RTM_GETROUTE(获取路由表)。

  • 配置内核RTM_NEWLINK(创建新接口)、RTM_SETLINK(修改接口属性)。

2. 内核 → 用户空间

内核通过 Netlink 消息主动通知用户程序事件。例如:

  • 接口状态变化:网络接口启用/禁用。

  • 新设备插入:USB 设备连接、Wi-Fi 网络扫描结果。

  • 路由表更新:路由条目添加或删除。


为什么用 Netlink?

与其他内核通信方式相比,Netlink 的优势在于:

机制特点适用场景
Netlink双向、异步、支持多播、结构化数据、可扩展动态配置和实时事件通知
Sysfs通过文件系统操作(/sys),读写简单但效率低静态配置(如设置参数)
Procfs通过文件系统(/proc),主要用于状态查询读取系统信息(如进程状态)
ioctl通过设备文件操作,接口不统一,扩展性差设备驱动特定操作
Netlink 的独特优势
  1. 结构化数据
    消息通过二进制格式传递,避免了文本解析(如 procfs/sysfs)的开销。

  2. 异步通信
    支持非阻塞通信,用户程序无需等待内核响应。

  3. 多播支持
    内核可以向多个用户进程广播事件(如接口状态变化)。

  4. 可扩展性
    通过消息类型(nlmsg_type)和属性(struct rtattr)灵活扩展功能。


Netlink 消息的工作流程

以获取网络接口列表为例:

  1. 用户程序构造请求消息

    • 设置 nlmsghdrnlmsg_type = RTM_GETLINKnlmsg_flags = NLM_F_DUMP

    • 设置 rtgenmsgrtgen_family = AF_UNSPEC(获取所有接口)。

  2. 发送消息到内核
    通过 sendmsg 系统调用发送 Netlink 消息。

  3. 内核处理请求
    路由子系统解析消息,收集所有网络接口信息,封装为多个 Netlink 消息(可能分片)。

  4. 用户程序接收响应
    通过 recvmsg 读取消息,解析 nlmsghdr 和消息体,提取接口名称、状态等数据。


典型应用场景

  1. 网络配置工具
    iproute2 工具集(如 ip linkip route)底层使用 Netlink 配置网络。

  1. 设备监控
    监听内核事件,如接口状态变化、新设备连接。

  2. 防火墙和策略路由
    配置 netfilter(iptables/nftables)规则或复杂路由策略。

  3. 容器网络
    容器运行时(如 Docker)通过 Netlink 管理虚拟网络设备。

 

1.nlinterfaces.c

// 程序功能:应用Netlink套接字从Linux内核打印输出所有网络接口名称
#include <bits/types/struct_iovec.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
#include <linux/netlink.h>  //Netlink协议相关定义
#include <linux/rtnetlink.h> // 路由相关的Netlink消息定义#define BUFSIZE 10240//定义一个自定义结构体ln_request_s,它包含一个 Netlink 消息头nlmsghdr和一个路由通用消息结构体rtgenmsg
struct In_request_s{//Netlink消息头struct nlmsghdr hdr;//路由消息通用结构,指定地址族struct rtgenmsg gen;
};//功能:解析并打印网络接口信息
void rtnl_print_link(struct nlmsghdr *h){//struct ifinfomsg *iface:指向 Netlink 消息中包含的网络接口信息结构体struct ifinfomsg *iface;//struct rtattr *attr:指向路由属性结构体struct  rtattr *attr;int len = 0;//获取 Netlink 消息中实际的数据部分,计算方式:消息头地址 + 头部大小iface = NLMSG_DATA(h);//获取 Netlink 消息中有效负载的长度len = RTM_PAYLOAD(h);//遍历路由属性for(attr = IFLA_RTA(iface);RTA_OK(attr,len);attr = RTA_NEXT(attr,len)){switch (attr->rta_type){//如果属性是接口名称就打印case IFLA_IFNAME:printf("接口名称%d : %s\n", iface->ifi_index, (char *)RTA_DATA(attr));break;default:break;}}
}int main(int argc,char *argv[]){//Netlink地址结构,用于绑定套接字struct sockaddr_nl nkernel;//消息头结构,用于 sendmsg 和 recvmsgstruct msghdr msg;//分散、聚集I/O结构,用于消息传输,主要跟readv、writev等缓冲区合并有关,用于一次I/O操作处理多个缓冲区struct iovec io;//自定义请求结构struct In_request_s req;//s为套接字描述符,end为循环结束标志int s = -1, end = 0, ret;//接收缓冲区char buf[BUFSIZE];//初始化Netlink地址结构memset(&nkernel,0,sizeof(nkernel));nkernel.nl_family = AF_NETLINK;    //这里与内核通信所以不使用AF_INETnkernel.nl_groups = 0; // 不加入任何组播组//创建套接字/*AF_NETLINK: 使用 Netlink 协议族。SOCK_RAW: 原始套接字类型,允许直接操作 Netlink 消息。NETLINK_ROUTE: 路由子系统,用于获取网络接口和路由信息。*/if ((s = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0){printf("创建Netlink套接字失败.\n");exit(EXIT_FAILURE);}//构造Netlink请求消息memset(&req, 0, sizeof(req));//#define NLMSG_LENGTH(len) ((len) + NLMSG_ALIGN(sizeof(struct nlmsghdr)))//nlmsg_len: 消息总长度(头部 + rtgenmsg 结构体),通过 NLMSG_LENGTH 计算对齐后的长度req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));//请求获取网络接口信息req.hdr.nlmsg_type = RTM_GETLINK;//标志为请求消息,并要求返回所有条目req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;//序列号,用于匹配请求和响应req.hdr.nlmsg_seq = 1;//发送方进程 IDreq.hdr.nlmsg_pid = getpid();//指定地址族为 IPv4(可改为 AF_UNSPEC 获取所有接口)req.gen.rtgen_family = AF_INET;//设置I/O向量和消息头memset(&io, 0, sizeof(io));io.iov_base = &req;io.iov_len = req.hdr.nlmsg_len;memset(&msg, 0, sizeof(msg));msg.msg_iov = &io;          // 指向 I/O 向量msg.msg_iovlen = 1;         // 向量数量为 1msg.msg_name = &nkernel;    // 目标地址(内核)msg.msg_namelen = sizeof(nkernel);//发送请求消息if ((ret = sendmsg(s, &msg, 0)) < 0) {perror("发送消息失败");close(s);exit(EXIT_FAILURE);}//接收并解析内核响应,,当接收到 NLMSG_DONE 消息时,end 会被置为 1,从而退出循环while(!end){//定义一个指向 nlmsghdr 结构体的指针 msg_ptr,用于遍历接收到的 Netlink 消息struct nlmsghdr *msg_ptr;//用于记录还未处理的消息长度int remaining_len;memset(buf, 0, BUFSIZE);io.iov_base = buf;io.iov_len = BUFSIZE;if ((ret = recvmsg(s, &msg, 0)) < 0) {if (errno == EINTR) continue;  // 处理中断perror("接收消息失败");close(s);exit(EXIT_FAILURE);}// 处理消息分片(NLMSG_TRUNC标志)if (msg.msg_flags & MSG_TRUNC) {fprintf(stderr, "警告:消息被截断,考虑增大缓冲区\n");}//将 msg_ptr 指针指向接收缓冲区 buf 的起始位置,将其视为第一个 Netlink 消息的头部msg_ptr = (struct nlmsghdr *)buf;//将 remaining_len 初始化为接收到的消息总长度 retremaining_len = ret;for (; NLMSG_OK(msg_ptr, remaining_len);   //NLMSG_OK(msg_ptr, remaining_len):这是一个宏,用于检查 msg_ptr 指向的 Netlink 消息是否有效,即消息长度是否足够且未超出剩余未处理的消息长度msg_ptr = NLMSG_NEXT(msg_ptr, remaining_len)) {  //将 msg_ptr 指针移动到下一个 Netlink 消息的头部,并更新 remaining_len 的值//内核在回复单播请求时,会将 nlmsg_pid 设置为用户进程的 PID(即 self_pid)if (msg_ptr->nlmsg_pid != getpid()) {fprintf(stderr, "收到非本进程的消息,已忽略 (PID: %u)\n", msg_ptr->nlmsg_pid);continue;}   switch (msg_ptr->nlmsg_type) {case NLMSG_ERROR: {  //如果消息类型为 NLMSG_ERROR,表示内核返回了错误信息struct nlmsgerr *err = NLMSG_DATA(msg_ptr);  //使用 NLMSG_DATA 宏获取消息中的错误信息结构体 nlmsgerr 的指针if (err->error != 0) {fprintf(stderr, "内核返回错误: %s\n", strerror(-err->error));close(s);exit(EXIT_FAILURE);}break;}case NLMSG_DONE: //如果消息类型为 NLMSG_DONE,表示内核已经发送完所有请求的信息,将 end 标志置为 1,退出循环end = 1;break;case RTM_NEWLINK: //如果消息类型为 RTM_NEWLINK,表示接收到了新的网络接口信息。调用 rtnl_print_link 函数处理该消息,打印网络接口的相关信息rtnl_print_link(msg_ptr);break;default:   //如果消息类型不是上述几种情况,输出忽略消息的信息,包含消息类型和消息长度printf("忽略消息:type=%d, len=%d\n",msg_ptr->nlmsg_type, msg_ptr->nlmsg_len);break;}}// 处理未对齐的剩余数据if (remaining_len > 0) {fprintf(stderr, "剩余%d字节未处理数据\n", remaining_len);}}close(s);  // 确保关闭套接字return 0;
}

编译运行:

二、ipaddress.c

// 显示IPv4,应用Netlink套接字从Linux内核中获取所有网络接口的IP地址
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <errno.h>#define BUFFERSIZE 10240// 定义一个自定义结构体 netlink_reqest_s,它包含一个 Netlink 消息头 nlmsghdr 和一个路由通用消息结构体 rtgenmsg
struct netlink_reqest_s {// Netlink 消息头struct nlmsghdr hdr;// 路由消息通用结构,指定地址族struct rtgenmsg gen;
};// 功能:解析并打印网络接口的 IP 地址信息
void rtnetlink_disp_address(struct nlmsghdr *h) {// struct ifaddrmsg *addr:指向 Netlink 消息中包含的网络地址信息结构体struct ifaddrmsg *addr;// struct rtattr *attr:指向路由属性结构体struct rtattr *attr;// 用于记录 Netlink 消息中有效负载的长度int len;// 获取 Netlink 消息中实际的数据部分,计算方式:消息头地址 + 头部大小addr = NLMSG_DATA(h);// 获取 Netlink 消息中有效负载的长度len = RTM_PAYLOAD(h);/* 循环输出 Netlink 所有属性消息:网络接口名称及 IP 地址 */for (attr = IFA_RTA(addr); RTA_OK(attr, len); attr = RTA_NEXT(attr, len)) {switch (attr->rta_type) {// 如果属性是接口名称就打印case IFA_LABEL:printf("网络接口名称 : %s\n", (char *)RTA_DATA(attr));break;// 如果属性是本地 IP 地址就打印case IFA_LOCAL: {// 获取 IP 地址的二进制表示int ip = *(int *)RTA_DATA(attr);// 用于存储 IP 地址的四个字节unsigned char bytes[4];// 提取 IP 地址的四个字节bytes[0] = ip & 0xFF;bytes[1] = (ip >> 8) & 0xFF;bytes[2] = (ip >> 16) & 0xFF;bytes[3] = (ip >> 24) & 0xFF;// 打印网络 IP 地址printf("网络 IP 地址为 : %d.%d.%d.%d\n\n", bytes[0], bytes[1], bytes[2], bytes[3]);break;}default:break;}}
}int main(void) {// Netlink 地址结构,用于绑定套接字struct sockaddr_nl kerl;// 套接字描述符int s;// 循环结束标志int end = 0;// 接收到的消息长度int len;// 消息头结构,用于 sendmsg 和 recvmsgstruct msghdr msg;// 自定义请求结构struct netlink_reqest_s req;// 分散、聚集 I/O 结构,用于消息传输struct iovec io;// 接收缓冲区char buffer[BUFFERSIZE];// 初始化 Netlink 地址结构memset(&kerl, 0, sizeof(kerl));// 使用 Netlink 协议族kerl.nl_family = AF_NETLINK;// 不加入任何组播组kerl.nl_groups = 0;// 创建套接字/*AF_NETLINK: 使用 Netlink 协议族。SOCK_RAW: 原始套接字类型,允许直接操作 Netlink 消息。NETLINK_ROUTE: 路由子系统,用于获取网络接口和路由信息。*/if ((s = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0) {perror("创建 Netlink 套接字失败");exit(EXIT_FAILURE);}// 构造 Netlink 请求消息memset(&req, 0, sizeof(req));// 消息总长度(头部 + rtgenmsg 结构体),通过 NLMSG_LENGTH 计算对齐后的长度req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));// 请求获取网络接口地址信息req.hdr.nlmsg_type = RTM_GETADDR;// 标志为请求消息,并要求返回所有条目req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;// 序列号,用于匹配请求和响应req.hdr.nlmsg_seq = 1;// 发送方进程 IDreq.hdr.nlmsg_pid = getpid();// 指定地址族为 IPv4req.gen.rtgen_family = AF_INET;// 设置 I/O 向量和消息头memset(&io, 0, sizeof(io));io.iov_base = &req;io.iov_len = req.hdr.nlmsg_len;memset(&msg, 0, sizeof(msg));msg.msg_iov = &io;          // 指向 I/O 向量msg.msg_iovlen = 1;         // 向量数量为 1msg.msg_name = &kerl;       // 目标地址(内核)msg.msg_namelen = sizeof(kerl);// 发送请求消息if (sendmsg(s, &msg, 0) < 0) {perror("发送消息失败");close(s);exit(EXIT_FAILURE);}// 接收并解析内核响应,当接收到 NLMSG_DONE 消息时,end 会被置为 1,从而退出循环while (!end) {// 定义一个指向 nlmsghdr 结构体的指针 msg_ptr,用于遍历接收到的 Netlink 消息struct nlmsghdr *msg_ptr;// 用于记录还未处理的消息长度int remaining_len;// 清空接收缓冲区memset(buffer, 0, BUFFERSIZE);io.iov_base = buffer;io.iov_len = BUFFERSIZE;// 接收消息if ((len = recvmsg(s, &msg, 0)) < 0) {if (errno == EINTR) continue;  // 处理中断perror("接收消息失败");close(s);exit(EXIT_FAILURE);}// 处理消息分片(NLMSG_TRUNC 标志)if (msg.msg_flags & MSG_TRUNC) {fprintf(stderr, "警告:消息被截断,考虑增大缓冲区\n");}// 将 msg_ptr 指针指向接收缓冲区 buffer 的起始位置,将其视为第一个 Netlink 消息的头部msg_ptr = (struct nlmsghdr *)buffer;// 将 remaining_len 初始化为接收到的消息总长度 lenremaining_len = len;for (; NLMSG_OK(msg_ptr, remaining_len);  // NLMSG_OK(msg_ptr, remaining_len):这是一个宏,用于检查 msg_ptr 指向的 Netlink 消息是否有效,即消息长度是否足够且未超出剩余未处理的消息长度msg_ptr = NLMSG_NEXT(msg_ptr, remaining_len)) {  // 将 msg_ptr 指针移动到下一个 Netlink 消息的头部,并更新 remaining_len 的值// 内核在回复单播请求时,会将 nlmsg_pid 设置为用户进程的 PID(即 self_pid)if (msg_ptr->nlmsg_pid != getpid()) {fprintf(stderr, "收到非本进程的消息,已忽略 (PID: %u)\n", msg_ptr->nlmsg_pid);continue;}switch (msg_ptr->nlmsg_type) {// 如果消息类型为 NLMSG_ERROR,表示内核返回了错误信息case NLMSG_ERROR: {// 使用 NLMSG_DATA 宏获取消息中的错误信息结构体 nlmsgerr 的指针struct nlmsgerr *err = NLMSG_DATA(msg_ptr);if (err->error != 0) {fprintf(stderr, "内核返回错误: %s\n", strerror(-err->error));close(s);exit(EXIT_FAILURE);}break;}// 如果消息类型为 NLMSG_DONE,表示内核已经发送完所有请求的信息,将 end 标志置为 1,退出循环case NLMSG_DONE:end = 1;break;// 如果消息类型为 RTM_NEWADDR,表示接收到了新的网络接口地址信息。调用 rtnetlink_disp_address 函数处理该消息,打印网络接口的相关信息case RTM_NEWADDR:rtnetlink_disp_address(msg_ptr);break;// 如果消息类型不是上述几种情况,输出忽略消息的信息,包含消息类型和消息长度default:printf("忽略消息:type=%d, len=%d\n", msg_ptr->nlmsg_type, msg_ptr->nlmsg_len);break;}}// 处理未对齐的剩余数据if (remaining_len > 0) {fprintf(stderr, "剩余 %d 字节未处理数据\n", remaining_len);}}// 确保关闭套接字close(s);return 0;
}    

编译运行:

http://www.dtcms.com/wzjs/256115.html

相关文章:

  • 徐州网站建设案例百度公司官方网站
  • 黑龙江省建设监理协会网站个人博客网页设计html
  • 微网站建设包括哪些内容今日资讯最新消息
  • 联通 网站备案长春seo招聘
  • 苏州创元投资集团网站关键一招
  • 网站设计兼职爱站网为什么不能用了
  • 做一钓鱼网站吗seo外包如何
  • 企业网站方案设计网站推广的途径有哪些
  • 韶关企业网站建设公司短视频培训要多少学费
  • 会员制网站建设百度引擎搜索推广
  • 网站建设北京女儿考试没圈关键词
  • cms模板seo网络推广优化教程
  • 网站建设168抖音seo关键词优化怎么做
  • 企业做网站etp和源程序交换链接平台
  • 免费模板网站制作全网营销有哪些平台
  • 电商网站怎么做seo优化网页设计费用报价
  • 龙岩网站建设大概费用seo网站
  • 专业网站建设模板下载seo网络优化教程
  • 天津网站建设公司百度提问
  • 有每天做任务赚钱的网站吗网站关键词快速优化
  • 网页搜索关键词网站seo推广
  • 建设网站怎么到工商备案推广普通话手抄报句子
  • 查询网站域名搭建一个网站需要多少钱?
  • 长沙人才app网站排名优化怎么做
  • 婚纱摄影网站图片艾滋病多久能查出来
  • 深圳做微网站上海百度研发中心
  • html网站怎么做网络营销推广策划步骤
  • 哪些网站可以做批发衣服惠州seo全网营销
  • wordpress 自动发卡珠海seo快速排名
  • 河南做外贸网站的公司南宁网站建设网站推广