- 论坛徽章:
- 0
|
原帖由 epegasus 于 2009-9-4 10:50 发表 ![]()
看来LZ和我一样喜欢臭屁,按我同事的观点,会用就行了管那么多做什么,
这是篇很不错的文章,虽然我还没有完全看懂(有不少错别字影响理解)
我有进一步几个疑问:
>>在某一个时刻inet发送他的recv类 ...
简单来说:
首先声明的是-》我说的recv和send列队只是个假设,真实的名字在sock结构体中的sk_receive_queue & sk_write_queue中。为了能说明这个东西到底是如何使用的,那我就来介绍一下rtnetlink的简单使用。
在rtnetlink中有三个消息模式:RTM_NEWLINK, RTM_DELLINK, RTM_GETLINK.
RTM-GETLINK:
是用来获取网卡的信息的。让我们看看该过程是怎么样使用的?
当用户空间发送该请求的时候,请注意,netlink_sendmsg会一直找到rtnetlink注册的那个函数rtnetlink_rcv,然后rtnetlink_rcv执行,因为网卡的信息都是固定存在的,所以rtnetlink_rcv几乎是用一种近似非阻塞的方式来获取这些网卡的数据,然后把这些数据追加到`recv`列队上,问题是它怎么知道哪个socket(pid)发送过来的,这个问题很简单socket被sock这个结构包含,而netlink_sock这个结构体包含sock,在netlink_sock这个结构体中又包括一个字段pid,这个pid就是用户空间的socket在nl_pid_hash中的索引,当netlink_sendmsg在根据目标pid(0)为0的时候调用netlink_unicast_kernel,让后再调用rtnetlink_rcv这个函数,而在此过程中sock这个结构体一直都是被传递的,根据sock这个结构题可以很方便的访问netlink_sock和socket这几个结构体。而这个时候,bind的地址几句是根本没有必要的,因为当用户空间在send返回的时候,它的接受列队上实际上就已经有数据了。而当send返回的时候,接着就可以调用recv来获取数据了。几乎可以想象整个过程都是无阻塞的。
在来看看那些异步的:
异步的事件如:网络地址的更改,arp缓冲区的修改等
相对于上面的GETLINK,这些则完全都是异步的,也就是说你完全不能说我发送一个请求说:send 内核,你赶紧的让ip地址修改,我要接受。这几乎是完全不可能的,而要接受这样的事件,你可以用setsockopt来调用NETLINK_ADD_MEMBERSHIP来告诉内核当什么事情发生的时候,让内核告诉你。然后你就可以用epoll来监听上面的事情了。当一个你希望的事情发生的时候,那个事情就加入到用户空间的socket的recv列队,然后epoll返回,获知当前有事。你甚至可以通过sk_filter来更细致的过滤你想要的事件。
参考资料:
rtnetlink_event
rtnl_register
rtnetlink_init
sk_filter
[ 本帖最后由 wojiaohesen 于 2009-9-4 13:34 编辑 ] |
|