Netlink与Genetlink接口执行流程简要分析:
netlink_proto_init ///< 内核层
proto_register(&netlink_proto, 0);
nl_table = kcalloc(MAX_LINKS, sizeof(*nl_table), GFP_KERNEL);
netlink_add_usersock_entry();
sock_register(&netlink_family_ops);
sys_socket ///< 应用层
retval = sock_create(family, type, protocol, &sock);
pf = rcu_dereference(net_families[family]);
err = pf->create(net, sock, protocol, kern);
netlink_create
__netlink_create(net, sock, cb_mutex, protocol, kern);
sk->sk_data_ready = sock_def_readable; ///< 应用层注册为-
sys_bind ///< bind之后可以使用 recv、recvmsg 接收消息
sock = sockfd_lookup_light(fd, &err, &fput_needed);
err = move_addr_to_kernel(umyaddr, addrlen, &address);
err = security_socket_bind(sock, (struct sockaddr *)&address, addrlen);
err = sock->ops->bind(sock, (struct sockaddr *)&address, addrlen);
sys_send ///< 内核层
sys_sendto
import_single_range(WRITE, buff, len, &iov, &msg.msg_iter);
sockfd_lookup_light(fd, &err, &fput_needed);
move_addr_to_kernel(addr, addr_len, &address);
sock_sendmsg(sock, &msg);
netlink_sendmsg
memcpy_from_msg(skb_put(skb, len), msg, len)
security_netlink_send(sk, skb);
/* 单播 */
netlink_unicast(sk, skb, dst_portid, msg->msg_flags&MSG_DONTWAIT);
netlink_unicast_kernel(sk, skb, ssk);
nlk->netlink_rcv(skb); ///< 之前 nlk_sk(sk)->netlink_rcv = cfg->input;
/* 多播 */
netlink_broadcast(sk, skb, dst_portid, dst_group, GFP_KERNEL);
netlink_broadcast_filtered
sk_for_each_bound(sk, &nl_table[ssk->sk_protocol].mc_list)
do_one_broadcast(sk, &info);
netlink_broadcast_deliver(sk, p->skb2);
__netlink_sendskb(sk, skb);
sk->sk_data_ready(sk);
BUG();
sys_recv ///< 内核层
sys_recvfrom
sock = sockfd_lookup_light(fd, &err, &fput_needed);
err = sock_recvmsg(sock, &msg, flags);
security_socket_recvmsg(sock, msg, msg_data_left(msg), flags);
sock_recvmsg_nosec(sock, msg, flags);
sock->ops->recvmsg(sock, msg, msg_data_left(msg), flags);
netlink_recvmsg
skb = skb_recv_datagram(sk, flags, noblock, &err);
__skb_try_recv_datagram
__skb_wait_for_more_packets
prepare_to_wait_exclusive(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); ///< 阻塞等待消息
nlmsg_unicast ///< 内核层
netlink_unicast(sk, skb, portid, MSG_DONTWAIT);
netlink_sendskb(sk, skb);
__netlink_sendskb(sk, skb);
sk->sk_data_ready(sk); ///< sock_def_readable
sock_def_readable
wake_up_interruptible_sync_poll(&wq->wait, POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND); ///< 唤醒
-------------------------------------------------------------------------------------------------------------
genetlink
genl_register_family(&genl_ctrl) ///< 内核层
genl_validate_ops(family);
family->id = idr_alloc(&genl_fam_idr, family, start, end + 1, GFP_KERNEL); ///< 加入genl_fam_idr, 分配ID
register_pernet_subsys(&genl_pernet_ops); ///< 注册netlink
.input = genl_rcv ///< 接收函数
netlink_rcv_skb(skb, &genl_rcv_msg);
family = genl_family_find_byid(nlh->nlmsg_type); ///< 通过ID找到family
genl_family_rcv_msg(family, skb, nlh, extack);
ops = genl_get_cmd(hdr->cmd, family);
nlmsg_parse(nlh, hdrlen, attrbuf, family->maxattr, ops->policy, extack);
tb[type] = (struct nlattr *)nla; ///< tb <==> attrbuf
info.attrs = attrbuf;
ops->doit(skb, &info);
if (info->attrs[CTRL_ATTR_FAMILY_NAME])
res = genl_family_find_byname(name);
msg = ctrl_build_family_msg(res, info->snd_portid, info->snd_seq, CTRL_CMD_NEWFAMILY);
genlmsg_reply(msg, info);
详细的分析过程可以查看这位博主的文章,很全面:blog.csdn.net/luckyapple1028/article/details/50839395