1. Generic Netlink 的数据结构
首先, Generic Netlink是按照Family管理的,内核的其它模块或子系统可以向它注册自己的Family. 所有的Family会存放在一张Hash链表上。
注册Family: - #define NLMSG_MIN_TYPE 0x10 /* < 0x10: reserved control messages */
- #define GENL_ID_GENERATE 0
- #define GENL_ID_CTRL NLMSG_MIN_TYPE
- #define GENL_MIN_ID NLMSG_MIN_TYPE
- #define GENL_MAX_ID 1023
如果Family ID是GENL_ID_GENERATE(被定义为0),则表示由系统自动分配ID,否则表示指定固定ID。 指定的ID必须在大于0x10并小于等于1023. 0x10被预留给CTRL_FAMILY.
自动分配ID的方法是从0x10开始找到第一个未被分配的ID。
可见Family ID是全局唯一的。
Family在Hash表上的位置由ID决定, ID & 0x0F, 也就是ID的低四Bit决定
Family name最好也是全局唯一的, 在genl_family_find_byname(char *name)函数中可见它是找到第一个匹配的name就返回的。
Family的maxattr:根据maxattr的值给struct nlattr ** attrbuf; 分配相应大小的内存。nlattr的作用后面会讲到。
每个Family都会有一个operations的列表,可以调用genl_register_ops()函数把各个ops添加到famliy 的ops_list;链表中。每个ops都有一个cmd和相应的Handler.
每个Family通常也都会有一个mc_group的列表。
每个mc_group都隶属于一个Famliy, 同一个Family内的mc_group不能有相同的name,
Name是由用户指定的,但是ID是由系统分配的,在genl_register_mc_group()函数里面会分配ID
分配ID的方法是:在起始地址为mc_groups的内存地方设置一个bitmap, bit0初始化为1, 然后寻找第一个为零的Bit,该Bit的位置即为mc_group的ID, 并把该Bit置为1
这个Bitmap初始化时只有32Bit空间,随着Group数目的增多会动态增大。
可见:mc_group的ID是全局唯一的。