现在的位置: 首页 > 综合 > 正文

Linux 网络系统学习 IPv6 的初始化(详细而全面)

2013年08月28日 ⁄ 综合 ⁄ 共 8178字 ⁄ 字号 评论关闭

转自:http://blog.csdn.net/rstevens/archive/2007/04/10/1559289.aspx

 

 

1.
  



网络子系统


1.1.                   




网络子系统概述

 

Linux
内核中,与网络相关的代码是一个相对独立的子系统,称为网络子系统。

网络子系统是一个层次化的结构,可分为以下几个层次:

 

1、

Socket


Linux
在发展过程中,采用
BSD socket APIs
作为自己的网络相关的
API
接口。同时,
Linux
的目标又要能支持各种不同的协议族,而且这些协议族都可以使用
BSD socket APIs
作为应用层的编程接口。因此,在
socket APIs
与协议族层之间抽象出一个
socket
层,用于将
user space

socket API
调用,转给具体的协议族做处理。

 

2、


协议族层(
INET
协议族、
INET6
协议族等)

Linux
网络子系统功能上相当完备,它不仅支持
INET
协议族(也就是通常所说的
TCP/IP stack
),而且还支持其它很多种协议族,如
DECnet, ROSE, NETBEUI
等。
INET6
就是一种新增加的协议族。

对于
INET

INET6
协议族来说,


又进一步划分为传输层和网络层。

 

3、


设备驱动层

设备驱动层则主要将协议族层与物理的网络设备隔离开。它不在本文的讨论范围之内。

 

 

下图是
Linux
网络系统层次结构图。



 

 

 

1.2.                   




网络子系统的初始化

 

·
       


Socket
层的初始化:

 

Init()->do_basic_setup()->sock_init()

 

Sock_init()
:对
sock

skbuff
结构进行
SLAB
内存的初始化工作

 

 

·
       


各种网络协议族的初始化:

 

Do_initcalls()

对于编译到内核中的功能模块(而不是以模块的形式动态加载),它的初始化函数会在这个地方被调用到。

 
          

内核映象中专门有一个初始化段,所有编译到内核中的功能模块的初始化函数都会加入到这个段中;而
do_initcalls()
就是依次执行初始化段中的这些函数。

           
INET

协议族通常是被编译进内核的;它的模块初始化函数是
net/ipv4/af_inet.c
中的
inet_init()

           


INET6
是作为一个模块编译的。它的模块初始化函数是
net/ipv6/af_inet6.c
中的
inet6_init()

           



2.
  



协议族


 

Linux
网络子系统可以支持不同的协议族,
Linux
所支持的协议族定义在
include/linux/socket.h

 

 

2.1.                   




协议族数据结构

 

协议族数据结构是
struct net_proto_family

 

struct
 net_proto_family {

            
int
                     family;

            
int
                     (
*
create)(
struct
 socket 
*
sock, 
int
 protocol);

            
short
                 authentication;

            
short
                 encryption;

            
short
                 encrypt_net;

            
struct
 module    
*
owner;

};

 

 

这个结构中,最重要的是
create
函数,一个新的协议族,必须提供此函数的实现。这是因为:
    

不同的网络协议族,从
user space
的使用方法来说,都是一样的,都是先调用
socket()
来创建一个
socket fd
,然后通过这个
fd
发送
/
接收数据。


user space
通过
socket()
系统调用进入内核后,根据第一个参数协议族类型,来调用相应协议族的
create()
函数。对
INET6
来说,这个函数是
inet6_create()

因此,要实现一个新的协议族,首先需要提供一个
create()
的实现。关于
create()
里面具体做了什么,后面再叙述。

Linux
系统通过这种方式,可以很方便的支持新的网络协议族,而不用修改已有的代码。这很好的符合了


“开
-
闭原则”,对扩展开放,对修改封闭。

 

 

2.2.                   




协议族注册

 

Linux
维护一个
struct net_proto_family  

的数组
net_families[]

如果要支持一个新的网络协议族,那么需要定义自己的
struct net_proto_family
,并且通过调用

sock_register

将它注册到
net_families[]
中。

 

 



3.
  


socket


层的主要数据结构


 

socket
层又叫
“socket access protocol layer”
。它处于
BSD socket APIs
与底层具体的协议族之间。这是一个抽象层,它起着承上启下的作用。在这一层的数据结构也有着这种特点。

 

 

3.1.                   



Struct socket


 


user space
,通过
socket()
创建的
socket fd
,在内核中对应的就是一个
struct socket

 

struct
 socket {

            socket_state                 state;

            unsigned 
long
                flags;

            
struct
 proto_ops           
*
ops;

            
struct
 fasync_struct       
*
fasync_list;

            
struct
 file                       
*
file;

            
struct
 sock                    
*
sk;

            wait_queue_head_t       wait;

            
short
                             type;

};

 



 

它定义于
include/linux/net.h




 

 

3.2.                   



Struct proto_ops


 

Struct socket

ops
域指向一个
struct proto_ops
结构,
struct proto_ops
定义于
include/linux/net.h
中,它是
socket
层提供给上层的接口,这个结构中,都是
BSD socket API
的具体实现的函数指针。

 

struct
 proto_ops {

            
int
                     family;

            
struct
 module    
*
owner;

            
int
                     (
*
release)   (
struct
 socket 
*
sock);

            
int
                     (
*
bind)      (
struct
 socket 
*
sock,

                                                      
struct
 sockaddr 
*
myaddr,

                                                      
int
 sockaddr_len);

            
int
                     (
*
connect)   (
struct
 socket 
*
sock,

                                                      
struct
 sockaddr 
*
vaddr,

                                                      
int
 sockaddr_len, 
int
 flags);

            
int
                     (
*
socketpair)(
struct
 socket 
*
sock1,

                                                      
struct
 socket 
*
sock2);

            
int
                     (
*
accept)    (
struct
 socket 
*
sock,

                                                      
struct
 socket 
*
newsock, 
int
 flags);

            
int
                     (
*
getname)   (
struct
 socket 
*
sock,

                                                      
struct
 sockaddr 
*
addr,

                                                      
int
 
*
sockaddr_len, 
int
 peer);

            unsigned 
int
       (
*
poll)      (
struct
 file 
*
file, 
struct
 socket 
*
sock,

                                                      
struct
 poll_table_struct 
*
wait);

            
int
                     (
*
ioctl)     (
struct
 socket 
*
sock, unsigned 
int
 cmd,

                                                      unsigned 
long
 arg);

            
int
                     (
*
listen)    (
struct
 socket 
*
sock, 
int
 len);

            
int
                     (
*
shutdown)  (
struct
 socket 
*
sock, 
int
 flags);

            
int
                     (
*
setsockopt)(
struct
 socket 
*
sock, 
int
 level,

                                                      
int
 optname, 
char
 __user 
*
optval, 
int
 optlen);

            
int
                     (
*
getsockopt)(
struct
 socket 
*
sock, 
int
 level,

                                                      
int
 optname, 
char
 __user 
*
optval, 
int
 __user 
*
optlen);

            
int
                     (
*
sendmsg)   (
struct
 kiocb 
*
iocb, 
struct
 socket 
*
sock,

                                                      
struct
 msghdr 
*
m, size_t total_len);

            
int
                     (
*
recvmsg)   (
struct
 kiocb 
*
iocb, 
struct
 socket 
*
sock,

                                                      
struct
 msghdr 
*
m, size_t total_len,

                                                      
int
 flags);

            
int
                     (
*
mmap)               (
struct
 file 
*
file, 
struct
 socket 
*
sock,

                                                      
struct
 vm_area_struct 
*
 vma);

            ssize_t              (
*
sendpage)  (
struct
 socket 
*
sock, 
struct
 page 
*
page,

                                                      
int
 offset, size_t size, 
int
 flags);

};

 

 

一个
socket API
通过系统调用进入内核后,首先由
socket
层处理。
Socket
层找到对应的
struct socket
,通过它找到
struct proto_ops
,然后由它所指向的函数进行进一步处理。

 


sendmsg()
这个函数为例,从
user space
通过系统调用进入
kernel
后,由
sys_sendmsg()

sock_sendmsg()
依次处理,然后交给
struct proto_ops

sendmsg()
处理。

 

 



4.
  



传输层、网络层的主要数据结构


 

Socket
层之下,是具体的协议族。


INET

INET6
来说,又分为传输层和网络层。

这两层重要的数据结构有
struct sock

struct proto

 

 

4.1.                   



Struct sock


 

struct sock
定义于
include/net/sock.h
中,用于
INET

INET6
协议族。

 

应用层的
socket fd
,在
socket
层对应的是
struct socket

struct socket
很简单,并不做什么具体的事情,它通过
sk
域与一个
struct sock
关联。因此,对应用层的一个
socket fd
来说,在内核中对应的是一个
struct socket
加上一个
struct sock
结构,
struct socket
负责
socket
层的处理,
struct sock
负责传输层、网络层的处理。

 


2.4
内核中,这个结构非常杂乱,到
2.6
内核,对它做了简化,但仍然有很多成员。我们在这里不具体了解它的作用,只要知道它所处的层次即可。

 

 

4.2.                   



Struct proto


 

struct sock
通过

sk_prot

域指向
struct proto
结构。

 

struct
 proto {

            
void
                              (
*
close)(
struct
 sock 
*
sk,

                                                            
long
 timeout);

            
int
                                 (
*
connect)(
struct
 sock 
*
sk,

                                                        
struct
 sockaddr 
*
uaddr,

                                                            
int
 addr_len);

            
int
                                 (
*
disconnect)(
struct
 sock 
*
sk, 
int
 flags);

 

            
struct
 sock 
*
                 (
*
accept) (
struct
 sock 
*
sk, 
int
 flags, 
int
 
*
err);

 

            
int
                                 (
*
ioctl)(
struct
 sock 
*
sk, 
int
 cmd,

                                                             unsigned 
long
 arg);

            
int
                                 (
*
init)(
struct
 sock 
*
sk);

            
int
                                 (
*
destroy)(
struct
 sock 
*
sk);

            
void
                              (
*
shutdown)(
struct
 sock 
*
sk, 
int
 how);

            
int
                                 (
*
setsockopt)(
struct
 sock 
*
sk, 
int
 level,

                                                            
int
 optname, 
char
 __user 
*
optval,

                                                            
int
 optlen);

            
int
                                 (
*
getsockopt)(
struct
 sock 
*
sk, 
int
 level,

                                                            
int
 optname, 
char
 __user 
*
optval,

                                                            
int
 __user 
*
option);        

            
int
                                 (
*
sendmsg)(
struct
 kiocb 
*
iocb, 
struct
 sock 
*
sk,

                                                               
struct
 msghdr 
*
msg, size_t len);

            
int
                                 (
*
recvmsg)(
struct
 kiocb 
*
iocb, 
struct
 sock 
*
sk,

                                               

【上篇】
【下篇】

抱歉!评论已关闭.