通过generic netlink可以实现内核和用户空间的通信,genetlink是通过family来管理的(哈希表),
genl_ctrl 是一个特殊的Family, 它是由Generic Netlink自己注册和实现,并用来查询Family列表、管理各个Family的添加、删除等事件的。用户空间先根据family name请求到相应的family ID,而后进行相互沟通。
static struct genl_family
genl_ctrl = {
.id = GENL_ID_CTRL,
.name = "nlctrl",
.version = 0x2,
.maxattr = CTRL_ATTR_MAX,
.netnsok = true,
};
static struct genl_ops genl_ctrl_ops = {
.cmd = CTRL_CMD_GETFAMILY,
.doit = ctrl_getfamily,
.dumpit = ctrl_dumpfamily,
.policy = ctrl_policy,
};
.id = GENL_ID_CTRL,
.name = "nlctrl",
.version = 0x2,
.maxattr = CTRL_ATTR_MAX,
.netnsok = true,
};
static struct genl_ops genl_ctrl_ops = {
.cmd = CTRL_CMD_GETFAMILY,
.doit = ctrl_getfamily,
.dumpit = ctrl_dumpfamily,
.policy = ctrl_policy,
};
static const struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] = {
[ CTRL_ATTR_FAMILY_ID] = { .type = NLA_U16 },
[CTRL_ATTR_FAMILY_NAME] = { .type = NLA_NUL_STRING, .len = L_NAMSIZ - 1 },
};
[ CTRL_ATTR_FAMILY_ID] = { .type = NLA_U16 },
[CTRL_ATTR_FAMILY_NAME] = { .type = NLA_NUL_STRING, .len = L_NAMSIZ - 1 },
};
genl_kern.c
#include <net/genetlink.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
/*netlink attributes 可以通过枚举索引找到对应的类型
*用户空间应用程序要传递这样的信息*/
enum {
DOC_EXMPL_A_UNSPEC,
DOC_EXMPL_A_MSG,
__DOC_EXMPL_A_MAX,
};
#define DOC_EXMPL_A_MAX (__DOC_EXMPL_A_MAX - 1)
/*atribute policy就是定义各个属性的具体类型,参见net/netlink.h*/
static struct nla_policy doc_exmpl_genl_policy[DOC_EXMPL_A_MAX + 1] = {
[DOC_EXMPL_A_MSG] = {.type = NLA_NUL_STRING},
};
#define VERSION_NR 1
//generic netlink family 定义
static struct genl_family doc_exmpl_genl_family = {
.id = GENL_ID_GENERATE,
.hdrsize = 0,
.name = "CONTROL_EXMPL",
.version = VERSION_NR,
.maxattr = DOC_EXMPL_A_MAX,
};
/*定义命令类型,用户空间以此来表明需要执行的命令*/
enum{
DOC_EXMPL_C_UNSPEC,
DOC_EXMPL_C_ECHO,
__DOC_EXMPL_C_MAX,
};
#define DOC_EXM