Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1509659
  • 博文数量: 228
  • 博客积分: 1698
  • 博客等级: 上尉
  • 技术积分: 3241
  • 用 户 组: 普通用户
  • 注册时间: 2008-12-24 21:49
个人简介

Linux

文章分类

全部博文(228)

文章存档

2017年(1)

2016年(43)

2015年(102)

2014年(44)

2013年(5)

2012年(30)

2011年(3)

分类: LINUX

2013-03-26 23:57:25

BSD socket
socket是用户API与网络协议栈之间的一个中间接口层,用户通过调用socket api将报文传给协议栈,或者从协议栈读取报文。
对于用户来说,socket就是一个打开的文件,linux内核中为socket定义了sockfs文件类型:
static struct file_system_type sock_fs_type = {
.name =  "sockfs",
.get_sb = sockfs_get_sb,
.kill_sb = kill_anon_super,
};
在sock_init中调用sock_fs_type的注册,文件系统存在后,创建socket,实际上是在sockfs文件系统中创建一个文件节点(inode),并建立struct inode和struct socket结构。
struct socket_alloc {
struct socket socket;
struct inode vfs_inode;
};
内核中实现了socket_alloc结构,将socket和vfs_inode封装在一起,这样通过vfs_inode和socket都可以互相找到对方,同时又保证了inode的独立性,适用于各种文件类型。
在sock_init中首先调用register_filesystem将sock_fs_type挂载全局的file_system链表上,然后调用vfs_kern_mount挂载该文件系统,这个过程会把sock文件系统的一些函
数操作集与超极块关联起来,这样当创建inode节点时,实际上最终使用的是sock文件系统提供的相关函数,这里不细述了,最终会一下申请处一个socket_alloc结构,同时
存在socket和vfs_inode。

接着看看通过task_struct怎么找到socket
current->file->fd_array[fd],fd是文件描述符,不能超过NR_OPEN_DEFAULT(32),通过fd找到file结构,这个结构中包含了目录项f_dentry,而f_dentry中包含了inode,
f_dentry通过inode刚好可以找到socket,这样通过进程描述符就找到了socket了。

下面看看具体的几个关键数据结构:
/**
*  struct socket - general BSD socket
*  @state: socket state (%SS_CONNECTED, etc)
*  @type: socket type (%SOCK_STREAM, etc)
*  @flags: socket flags (%SOCK_ASYNC_NOSPACE, etc)
*  @ops: protocol specific socket operations
*  @fasync_list: Asynchronous wake up list
*  @file: File back pointer for gc
*  @sk: internal networking protocol agnostic socket representation
*  @wait: wait queue for several uses
*/
struct socket {
socket_state  state; // 未分配、未连接、正连接、已连接、断连接,只对TCP生效s
short   type; // socket类型,如SOCK_DGRAM=1,SOCK_STREAM=2,SOCKET_RAW=3

unsigned long  flags; // 无使用
struct fasync_struct *fasync_list;
wait_queue_head_t wait;

struct file  *file;
struct sock  *sk; // 网络层sock的表示,这个是重点,整个协议栈都是围绕这个成员展开
const struct proto_ops *ops; // 操作集,分别对应流协议、数据报和原始套接口协议
};

这样通过文件描述符,可以找到中间层socket,通过socket可以找到网络层的sock,进而操作数据,收发包,这样就展开了。

sock的结构比较复杂,单独进行分析,下面主要讲socket、sock、tcp sock、inet_connection_sock、inet socket等的关系理一下
1. 通过fd可以找到socket,socket->sk指向了struct sock结构
2. struct sock->sk_socket指向了BSD socket,这样socket和sock可以轻松的互相查询
3. 数据报文在tcp入口,通过ip、端口等信息查询到struct sock信息
4. 如果是tcp协议,tcp_sock = struct tcp_sock *tp = tcp_sk(sk);可以强制转换,看一下这几个结构
struct tcp_sock {
/* inet_connection_sock has to be the first member of tcp_sock */
struct inet_connection_sock inet_conn;
......
struct udp_sock {
    /* inet_sock has to be the first member */
    struct inet_sock inet;
......
struct inet_connection_sock {
/* inet_sock has to be the first member! */
struct inet_sock   icsk_inet;
......
struct inet_sock {
/* sk and pinet6 has to be the first two members of inet_sock */
struct sock  sk;
......
inet_sock是INET域专用的一个sock表示,在struct sock上扩展而来,除基本sock属性,提供了INET域专用的属性,如TTL、IP地址、端口等
inet_connection_sock是所有面向连接的协议的socket的相关信息,第一个域是inet_sock,可以方便转换
tcp_sock是tcp协议的专用socket表示,在inet_connection_sock基础上扩展,主要增加了滑动窗口协议、拥塞控制算法等TCP专有属性
udp_sock第一个域也是inet_socket,包括一些加密相关的信息接口,暂时不分析

阅读(6183) | 评论(0) | 转发(3) |
给主人留下些什么吧!~~