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
来源: http://www.bubuko.com/infodetail-3359291.html