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

视频网站做视频容易火郑州seo培训班

视频网站做视频容易火,郑州seo培训班,中天建设集团有限公司西南分公司,投资者网站建设目录 简介: 一、Connector数据结构和 API 1、数据结构体 1.1 消息头结构体 1.2 连接器id结构体 1.3 netlink参数结构体 2、注册callback 3、卸载callback 4、发送消息 二、参考示例 1、用户态使用连接器 2、内核态使用连接器 简介: 连接器是一…

目录

简介:

一、Connector数据结构和 API

1、数据结构体

1.1 消息头结构体

1.2 连接器id结构体

1.3 netlink参数结构体

2、注册callback

3、卸载callback

4、发送消息

二、参考示例

1、用户态使用连接器

2、内核态使用连接器


简介:


        连接器是一种用户态与内核态的通信方式,本质上,连接器是一种netlink,它的 netlink 协议号为 NETLINK_CONNECTOR,与一般的 netlink 相比,它提供了更容易的使用接口。目前,稳定内核有两个连接器应用实例,一个是进程事件连接器,另一个是 CIFS 文件系统。连接器实现代码在内核的 driver/connector 目录中。用户可以配置内核菜单选择是否启用连接器。

        任何内核模块要想使用连接器,必须先注册一个标识 ID 和 回调函数,当连接器收到 netlink 消息后,会根据消息对应的标识 ID 调用相应该 ID 的回调函数。

连接器系统框架如图:

一、Connector数据结构和 API


1、数据结构体


1.1 消息头结构体

/* include/uapi/linux/netlink.h */
struct nlmsghdr {__u32		nlmsg_len;	/* Length of message including header */__u16		nlmsg_type;	/* Message content */__u16		nlmsg_flags;	/* Additional flags */__u32		nlmsg_seq;	/* Sequence number */__u32		nlmsg_pid;	/* Sending process port ID */
};

       

1.2 连接器id结构体

        struct cb_id 是连接器实例的标识 ID,它用于确定 netlink 消息与回调函数的对应关系。当连接器接收到标识 ID 为 {idx,val} 的 netlink 消息时,注册的回调函数 void (*callback) (void *) 将被调用。该回调函数的参数为结构 struct cn_msg 的指针

/* include/uapi/linux/connector.h */
struct cb_id {__u32 idx;__u32 val;
};struct cn_msg {struct cb_id id;__u32 seq;__u32 ack;__u16 len;		/* Length of the following data */__u16 flags;__u8 data[0];
};

1.3 netlink参数结构体

/* 源码路径:include/linux/netlink.h */
struct netlink_skb_parms {struct scm_creds	creds;		/* Skb credentials	*/__u32			portid;__u32			dst_group;__u32			flags;struct sock		*sk;bool			nsid_is_set;int			nsid;
};

2、注册callback


接口函数 cn_add_callback 用于向连接器注册新的连接器实例以及相应的回调函数

int cn_add_callback(struct cb_id *id, const char *name,void (*callback)(struct cn_msg *,struct netlink_skb_parms *))

功能:向连接器注册新的连接器实例,当收到标识ID则callback函数被调用

参数:

  • id :注册的标识 ID;
  • name :连接器回调函数的符号名;
  • callback :回调函数

3、卸载callback


接口函数 cn_del_callback 用于卸载回调函数

void cn_del_callback(struct cb_id *id)

功能:卸载callback函数

参数:

  • id:卸载 cn_add_callback 时注册的 id;

4、发送消息


接口函数 cn_netlink_send 用于向指定的组发送消息(用于向用户态发送netlink消息),它可以在任何上下文安全地调用,但是,如果内存不足,可能会发送失败

int cn_netlink_send(struct cn_msg *msg, u32 portid, u32 __group, gfp_t gfp_mask)

功能:向给定的组发送消息(向用户态发送netlink消息)

参数:

  • msg:netlink 消息的消息头;
  • __group:接收消息的组。如果它为 0,那么连接器将搜索所有注册的连接器用户,最终将发送给用户 ID 与在 msg 中的 ID 相同的组,但如果 __group 不为 0,消息将发送给 __group 指定的组;
  • gfp_mask:页分配标志;

二、参考示例

ncp 为 Netlink Connector Process,即用户态我们需要开发的程序

1、用户态使用连接器

实现了用户态发送/接收连接器msg

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <string.h>
#include <linux/netlink.h>/* CN_NETLINK_USERS 定义在 include/uapi/linux/connector.h */
#define CN_VIF_ID CN_NETLINK_USERS + 3
#define CN_VIF_VAL 0x5555#define RX_BUF_SIZE		100		//接收buf size
#define MAX_PLOAD		100		//发送message内存sizetypedef struct
{struct nlmsghdr hdr;char msg[RX_BUF_SIZE];
}RX_KERNEL_MSG;static int nl_connector_send(int _skfd, char *_pBuf, int _len)
{static int seq = 0;int ret = -1;struct nlmsghdr *nlhdr;struct cn_msg *cnmsg;/* 配置消息头 */nlhdr = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PLOAD));	//申请buf//初始化头 nlmsghdrmemset(nlhdr, 0, sizeof(struct nlmsghdr));nlhdr->nlmsg_len = NLMSG_SPACE(_len); //包括netlink消息头在内,整个消息长度 nlhdr->nlmsg_flags = 0;            //消息标志nlhdr->nlmsg_type = NLMSG_DONE;    //消息类型nlhdr->nlmsg_seq = 0;              //消息报文的序列号nlhdr->nlmsg_pid = getpid();		//消息中加入本应用端口pid/* 设置数据 */cnmsg = (struct cn_msg*)NLMSG_DATA(nlhdr);	//找到存放 cn_msg 的地址cnmsg->id.idx = CN_VIF_ID;cnmsg->id.val = CN_VIF_VAL;cnmsg->seq = seq++;cnmsg->ack = 0;memcpy(cnmsg->data, _pBuf, _len);	//这里要注意越界风险cnmsg->len = _len;/* 发送数据 */ret = send(_skfd, nlhdr, nlhdr->nlmsg_len, 0);	//将message消息发送给内核if(!ret){perror("Failed to send:");exit(-1);}free((void *)nlhdr);return ret;
}static int nl_connector_recv(int _skfd, char *_pBuf, int _len)
{int ret = -1;struct nlmsghdr *nlhdr_rx;char *pData;len = recv(_skfd, _pBuf, _len, 0);if (len == -1) {log_e("recv buf failed\n");// close(ksif->fd);return -1;}nlhdr_rx = (struct nlmsghdr *)_pBuf;				//msg头部分pData = (struct cn_msg *)NLMSG_DATA(nlhdr_rx);		//数据部分//判断msc头类型switch (nlhdr_rx->nlmsg_type) {case NLMSG_ERROR:printf("Error message received.\n");ret = 0;break;case NLMSG_DONE:ret = len;if(data->id.idx != CN_VIF_ID || data->id.val != CN_VIF_VAL)return 0;printf("[%x.%x] [%08u.%08u] %dbytes\n", data->id.idx, data->id.val, data->seq, data->ack, data->len);break;default:break;}return ret;
}int main(int argc, char* argv[])
{char *data = "This message is from user's space";char rx_buf[NL_SPACE(MAX_PLOAD)];//初始化struct sockaddr_nl l_local = {0};    //sockaddr_nl 是 netlink 使用的地址数据结构int skfd = -1;int seq = 0;int ret = -1;/* 1.创建NETLINK socket */skfd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);if(skfd < 0){printf("can not connect to kernel by netlink type %d\n", NETLINK_CONNECTOR);return -1;}//初始化 netlink 地址l_local.nl_family = AF_NETLINK;l_local.nl_pid = getpid();l_local.nl_groups = -1;	//请求组的位掩码,-1转为无符号32位的0xffffffff(表示都接收)if(bind(skfd, (struct sockaddr *)&l_local, sizeof(struct sockaddr_nl)) != 0){printf("bind() error\n");close(skfd);return -1;}/* 2.发送数据 */nl_connector_send(skfd, (char *)data, sizeof(data));/* 3.接收内核发来的信息 */nl_connector_recv(skfd, (char *)rx_buf, sizeof(rx_buf));printf("User Receive ACK from kernel:%s\r\n",(char *)info.msg);//内核和用户进行通信close(skfd);return 0;
}

2、内核态使用连接器

实现内核态接收/发送连接器msg

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <net/sock.h>
#include <linux/netlink.h>
#include <linux/connector.h>
#include <uapi/linux/connector.h>/* 连接器的唯一标识,连接器需要它来找到对应的连接器实例 */
#define CN_VIF_ID CN_NETLINK_USERS + 3
#define CN_VIF_VAL 0x5555static struct cb_id g_cb_id = { CN_VIF_ID, CN_VIF_VAL };/* cn 发送 */
static int cn_func_send(const uint8_t *_pBuf, size_t _len)
{struct cn_msg *m;static int seq_cnt = 0;m = kzalloc(sizeof(*m) + _len, GFP_ATOMIC);if (!m) {printk("kzalloc cn_msg failed\n");return 0;}m->id.idx = CN_VIF_ID;m->id.val = CN_VIF_VAL;m->seq = seq_cnt++;m->len = _len;memcpy(m + 1, _pBuf, m->len);//#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0)cn_netlink_send(m, 0, 0, GFP_ATOMIC);
//#else
//	cn_netlink_send(m, 0, GFP_ATOMIC);
//#endifkfree(m);return _len;
}/* 接收回调函数 */
static void cn_func_callback(struct cn_msg *cn_msg, struct netlink_skb_parms *nsp)
{/* 打印接收到的数据和长度 */printk("kernel space Rx: data: %s, len: %d\n", cn_msg->data, cn_msg->len);/* 内核态应答数据 */cn_func_send("kernel space Tx: ACK", sizeof("kernel space Tx: ACK"));
}int __init netlink_connector_init(void)
{int ret = -1;/* 注册 cn 接收回调函数 */ret = cn_add_callback(&g_cb_id, "cn_func", cn_func_callback);if(ret) {pr_err("cn_add_callback cn_func failed\n");return ret;}printk(KERN_DEBUG "netlink_connector_init!!\n");return ret;
}void __exit netlink_connector_exit(void)
{cn_del_callback(&g_cb_id);printk(KERN_DEBUG "netlink_connector_exit!!\n");
}module_init(netlink_connector_init);
module_exit(netlink_connector_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("dongao");

驱动加载后查看结果:

$ cat /proc/net/connector
Name            ID
cn_func         14:21845

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

相关文章:

  • 阿里巴巴官方网站兰州关键词快速上首页排名
  • 做网站例子图片描述百度app下载安装官方免费下载
  • wordpress tob5.0优化设计单元测试卷答案
  • 如何做别人的网站源云推广
  • 淮北官方网站自己创建一个网站需要多少钱
  • 商标设计注册搜索引擎优化实训心得
  • 设计用的报价网站管理培训课程
  • 单页面网站怎么做的大数据营销软件
  • 网站怎么做图片滚动制作网页的基本步骤
  • 福建省建设厅官方网站谁能给我个网址
  • 规模以上工业企业的标准seo日常工作内容
  • 网站怎么做图片按按钮跳转企业网站建设cms
  • 信阳市人民政府门户网站网站运营与维护
  • 网站开发属于什么系统seo首页优化
  • 口碑好的网站定制公司图片搜索
  • 电脑上建设银行网站打不开开一个免费网站
  • 苏州做代驾司机哪个网站好国内搜索引擎排名2022
  • 用vs2012做网站案例百度百度一下你就知道主页
  • 广州三合一企业网站哪家好seo大全
  • 外国一些做环保袋的网站查网站域名
  • 有什么网站是做批发的站长工具域名查询
  • 做任务给钱的网站网络推广员上班靠谱吗
  • 简单网站后台如何快速搭建一个网站
  • 临沧网站搭建爱站网怎么使用
  • wordpress本地写文章网站关键字优化技巧
  • 睢宁做网站磁力珠
  • 遵义网站建设txwl江苏seo推广
  • wordpress网页游戏模板河南seo技术教程
  • seo公司网站微博推广有用吗
  • 网站用什么东西做吴江seo网站优化软件