linux内核网络栈---socket调用内核路径
一、linux内核网络栈代码的准备知识1. linux内核ipv4网络部分分层结构: BSD socket层: 这一部分处理BSD socket相关操作,每个socket在内核中以struct socket结构体现。这一部分的文件 主要有:/net/socket.c /net/protocols.c etcINET socket层:BSD socket是个可以用
·
一、linux内核网络栈代码的准备知识
1. linux内核ipv4网络部分分层结构:
BSD socket层: 这一部分处理BSD socket相关操作,每个socket在内核中以struct socket结构体现。这一部分的文件
主要有:/net/socket.c /net/protocols.c etc
INET socket层:BSD socket是个可以用于各种网络协议的接口,而当用于tcp/ip,即建立了AF_INET形式的socket时,
INET socket层:BSD socket是个可以用于各种网络协议的接口,而当用于tcp/ip,即建立了AF_INET形式的socket时,
还需要保留些额外的参数,于是就有了struct sock结构。文件主要
有:/net/ipv4/protocol.c /net/ipv4/af_inet.c /net/core/sock.c etc
TCP/UDP层:处理传输层的操作,传输层用struct inet_protocol和struct proto两个结构表示。文件主要
TCP/UDP层:处理传输层的操作,传输层用struct inet_protocol和struct proto两个结构表示。文件主要
有:/net /ipv4/udp.c /net/ipv4/datagram.c /net/ipv4/tcp.c /net/ipv4/tcp_input.c /net/ipv4//tcp_output.c /net/ipv4/tcp_minisocks.c /net/ipv4/tcp_output.c /net/ipv4/tcp_timer.c
etc
IP层:处理网络层的操作,网络层用struct packet_type结构表示。文件主要有:/net/ipv4/ip_forward.c
IP层:处理网络层的操作,网络层用struct packet_type结构表示。文件主要有:/net/ipv4/ip_forward.c
ip_fragment.c ip_input.c ip_output.c etc.
数据链路层和驱动程序:每个网络设备以struct net_device表示,通用的处理在dev.c中,驱动程序都在/driver/net目
数据链路层和驱动程序:每个网络设备以struct net_device表示,通用的处理在dev.c中,驱动程序都在/driver/net目
录下。
2. 两台主机建立udp通信所走过的函数列表
^
| sys_read fs/read_write.c
| sock_read net/socket.c
| sock_recvmsg net/socket.c
| inet_recvmsg net/ipv4/af_inet.c
| udp_recvmsg net/ipv4/udp.c
| skb_recv_datagram net/core/datagram.c
| -------------------------------------------
| sock_queue_rcv_skb include/net/sock.h
| udp_queue_rcv_skb net/ipv4/udp.c
| udp_rcv net/ipv4/udp.c
| ip_local_deliver_finish net/ipv4/ip_input.c
| ip_local_deliver net/ipv4/ip_input.c
| ip_recv net/ipv4/ip_input.c
| net_rx_action net/dev.c
| -------------------------------------------
| netif_rx net/dev.c
| el3_rx driver/net/3c309.c
| el3_interrupt driver/net/3c309.c
==========================
| sys_write fs/read_write.c
| sock_writev net/socket.c
| sock_sendmsg net/socket.c
| inet_sendmsg net/ipv4/af_inet.c
| udp_sendmsg net/ipv4/udp.c
| ip_build_xmit net/ipv4/ip_output.c
| output_maybe_reroute net/ipv4/ip_output.c
| ip_output net/ipv4/ip_output.c
| ip_finish_output net/ipv4/ip_output.c
| dev_queue_xmit net/dev.c
| --------------------------------------------
| el3_start_xmit driver/net/3c309.c
V
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
==========================
|
|
|
|
|
|
|
|
|
|
|
|
V
3. 网络路径图、重要数据结构sk_buffer及路由介绍
4. 从连接、发送、到接收数据包的过程
二.linux的tcp-ip栈代码的详细分析
1.数据结构(msghdr,sk_buff,socket,sock,proto_ops,proto)
bsd套接字层,操作的对象是socket,数据存放在msghdr这样的数据结构:
创 建socket需要传递family,type,protocol三个参数,创建socket其实就是创建一个socket实例,然后创建一 个文件描述符结构,并且互相建立一些关联,即建立互相连接的指针,并且初始化这些对文件的写读操作映射到socket的read,write函数上来。
同 时初始化socket的操作函数(proto_ops结构),如果传入的type参数是STREAM类型,那么就初始化为 SOCKET->ops为inet_stream_ops,如果是DGRAM类型,则SOCKET-ops为inet_dgram_ops。对于 inet_stream_ops其实是一个结构体,包含了stream类型的socket操作的一些入口函数,在这些函数里主要做的是对socket进行 相关的操作,同时通过调用下面提到的sock中的相关操作完成socket到sock层的传递。比如在inet_stream_ops里有个 inet_release的操作,这个操作除了释放socket的类型空间操作外,还通过调用socket连接的sock的close操作,对于 stream类型来说,即tcp_close来关闭sock
释放sock。
创 建socket同时还创建sock数据空间,初始化sock,初始化过程主要做的事情是初始化三个队列,receive_queue(接收到 的数据包sk_buff链表队列),send_queue(需要发送数据包的sk_buff链表队列),backlog_queue(主要用于tcp中三 次握手成功的那些数据包,自己猜的),根据family、type参数,初始化sock的操作,比如对于family为inet类型的,type为 stream类型的,sock->proto初始化为tcp_prot.其中包括stream类型的协议sock操作对应的入口函数。
在 一端对socket进行write的过程中,首先会把要write的字符串缓冲区整理成msghdr的数据结构形式(参见linux内核 2.4版源代码分析大全),然后调用sock_sendmsg把msghdr的数据传送至inet层,对于msghdr结构中数据区中的每个数据包,创建 sk_buff结构,填充数据,挂至发送队列。一层层往下层协议传递。一下每层协议不再对数据进行拷贝。而是对sk_buff结构进行操作。
inet套接字及以下层 数据存放在sk_buff这样的数据结构里:
路由:
数据链路层:
unregister_netdev。
2.启动分析
void __init sock_init(void)
{
int i;
{
#ifdef SLAB_SKB
skb_init();
#endif
#endif
#ifdef CONFIG_WAN_ROUTER
wanrouter_init();
#endif
#endif
#ifdef CONFIG_NET
rtnetlink_init();
#endif
#ifdef CONFIG_NETLINK_DEV
init_netlink();
#endif
#ifdef CONFIG_NETFILTER
netfilter_init();
#endif
#endif
#ifdef CONFIG_NETLINK_DEV
#endif
#ifdef CONFIG_NETFILTER
#endif
#ifdef CONFIG_BLUEZ
bluez_init();
#endif
#endif
#ifdef CONFIG_IPSEC
#endif
}
(例 如inet_init函数以_init开头表示是系统初始化时做,函数结束后跟 module_init(inet_init),这是一个宏,在include/linux/init.c中定义,展开为 _initcall(inet_init),表示这个函数在do_initcalls被调用了)
此处主要列举inet协议的初始化过程。
static int __init inet_init(void)
{
struct sk_buff *dummy_skb;
struct inet_protocol *p;
struct inet_protosw *q;
struct list_head *r;
{
#ifdef CONFIG_NET_IPIP
#endif
#ifdef CONFIG_NET_IPGRE
#endif
#if defined(CONFIG_IP_MROUTE)
#endif
#ifdef CONFIG_PROC_FS
#endif
}
module_init(inet_init);
3.网络设备驱动程序(略)
4.网络连接
各层主要函数以及位置功能说明:
各层主要函数以及位置功能说明:
转载链接:
linux内核网络栈---socket调用内核路径 http://blog.sina.com.cn/s/blog_533074eb01013vzx.html
更多推荐
已为社区贡献2条内容
所有评论(0)