原文地址:http://anders0913.iteye.com/blog/411986

用户使用socket系统调用编写应用程序时,通过一个数字来表示一个socket,所有的操作都在该数字上进行,这个数字称为套接字描述符。在系统调用 的实现函数里,这个数字就会被映射成一个表示socket的结构体,该结构体保存了该socket的所有属性和数据。在内核的协议中实现中,关于表示 socket的结构体,是一个比较复杂的东西,下面一一介绍。 
    struct socket。 
    这是一个基本的BSD socket,我们调用socket系统调用创建的各种不同类型的socket,开始创建的都是它,到后面,各种不同类型的socket在它的基础上进行 各种扩展。struct socket是在虚拟文件系统上被创建出来的,可以把它看成一个文件,是可以被安全地扩展的。下面是其完整定义:

  1. struct socket {
  2. socket_state            state;
  3. unsigned long           flags;
  4. const struct proto_ops *ops;
  5. struct fasync_struct    *fasync_list;
  6. struct file             *file;
  7. struct sock             *sk;
  8. wait_queue_head_t       wait;
  9. short                   type;
  10. };

state用于表示socket所处的状态,是一个枚举变量,其类型定义如下:

  1. typedef enum {
  2. SS_FREE = 0,            //该socket还未分配
  3. SS_UNCONNECTED,         //未连向任何socket
  4. SS_CONNECTING,          //正在连接过程中
  5. SS_CONNECTED,           //已连向一个socket
  6. SS_DISCONNECTING        //正在断开连接的过程中
  7. }socket_state;

该成员只对TCP socket有用,因为只有tcp是面向连接的协议,udp跟raw不需要维护socket状态。 
    flags是一组标志位,在内核中并没有发现被使用。 
    ops是协议相关的一组操作集,结构体struct proto_ops的定义如下:

  1. struct proto_ops {
  2. int     family;
  3. struct module   *owner;
  4. int (*release)(struct socket *sock);
  5. int (*bind)(struct socket *sock, struct sockaddr *myaddr, int sockaddr_len);
  6. int (*connect)(struct socket *sock, struct sockaddr *vaddr, int sockaddr_len, int flags);
  7. int (*socketpair)(struct socket *sock1, struct socket *sock2);
  8. int (*accept)(struct socket *sock,struct socket *newsock, int flags);
  9. int (*getname)(struct socket *sock, struct sockaddr *addr,int *sockaddr_len, int peer);
  10. unsigned int (*poll)(struct file *file, struct socket *sock,
  11. struct poll_table_struct *wait);
  12. int (*ioctl)(struct socket *sock, unsigned int cmd, unsigned long arg);
  13. int (*listen)(struct socket *sock, int len);
  14. int (*shutdown)(struct socket *sock, int flags);
  15. int (*setsockopt)(struct socket *sock, int level,
  16. int optname, char __user *optval, int optlen);
  17. int (*getsockopt)(struct socket *sock, int level,
  18. int optname, char __user *optval, int __user *optlen);
  19. int (*sendmsg)(struct kiocb *iocb, struct socket *sock,
  20. struct msghdr *m, size_t total_len);
  21. int (*recvmsg)(struct kiocb *iocb, struct socket *sock,
  22. struct msghdr *m, size_t total_len, int flags);
  23. int (*mmap)(struct file *file, struct socket *sock,struct vm_area_struct * vma);
  24. ssize_t (*sendpage)(struct socket *sock, struct page *page,
  25. int offset, size_t size, int flags);
  26. };

协议栈中总共定义了三个strcut proto_ops类型的变量,分别是myinet_stream_ops, myinet_dgram_ops, myinet_sockraw_ops,对应流协议, 数据报和原始套接口协议的操作函数集。 
    type是socket的类型,对应的取值如下:

  1. enum sock_type {
  2. SOCK_DGRAM = 1,
  3. SOCK_STREAM = 2,
  4. SOCK_RAW    = 3,
  5. SOCK_RDM    = 4,
  6. SOCK_SEQPACKET = 5,
  7. SOCK_DCCP   = 6,
  8. SOCK_PACKET = 10,
  9. };

sk是网络层对于socket的表示,结构体struct sock比较庞大,这里不详细列出,只介绍一些重要的成员, 
    sk_prot和sk_prot_creator,这两个成员指向特定的协议处理函数集,其类型是结构体struct proto,该结构体也是跟struct proto_ops相似的一组协议操作函数集。这两者之间的概念似乎有些混淆,可以这么理解,struct proto_ops的成员操作struct socket层次上的数据,处理完了,再由它们调用成员sk->sk_prot的函数,操作struct sock层次上的数据。即它们之间存在着层次上的差异。struct proto类型的变量在协议栈中总共也有三个,分别是mytcp_prot,myudp_prot,myraw_prot,对应TCP, UDP和RAW协议。 
    sk_state表示socket当前的连接状态,是一个比struct socket的state更为精细的状态,其可能的取值如下:

  1. enum {
  2. TCP_ESTABLISHED = 1,
  3. TCP_SYN_SENT,
  4. TCP_SYN_RECV,
  5. TCP_FIN_WAIT1,
  6. TCP_FIN_WAIT2,
  7. TCP_TIME_WAIT,
  8. TCP_CLOSE,
  9. TCP_CLOSE_WAIT,
  10. TCP_LAST_ACK,
  11. TCP_LISTEN,
  12. TCP_CLOSING,
  13. TCP_MAX_STATES
  14. ;

这些取值从名字上看,似乎只使用于TCP协议,但事实上,UDP和RAW也借用了其中一些值,在一个socket创建之初,其取值都是 TCP_CLOSE,一个UDP socket connect完成后,将这个值改为TCP_ESTABLISHED,最后,关闭sockt前置回TCP_CLOSE,RAW也一样。 
    sk_rcvbuf和sk_sndbuf分别表示接收和发送缓冲区的大小。sk_receive_queue和sk_write_queue分别为接收缓 冲队列和发送缓冲队列,队列里排列的是套接字缓冲区struct sk_buff,队列中的struct sk_buff的字节数总和不能超过缓冲区大小的设定。

接着上一篇,继续介绍struct sock。 
    sk_rmem_alloc, sk_wmem_alloc和sk_omem_alloc分别表示接收缓冲队列,发送缓冲队列及其它缓冲队列中已经分配的字节数,用于跟踪缓冲区的使用情况。 
    struct sock有一个struct sock_common成员,因为struct inet_timewait_sock也要用到它,所以把它单独归到一个结构体中,其定义如下:

  1. struct sock_common {
  2. unsigned short      skc_family;
  3. volatile unsigned char skc_state;
  4. unsigned char       skc_reuse;
  5. int         skc_bound_dev_if;
  6. struct hlist_node   skc_node;
  7. struct hlist_node   skc_bind_node;
  8. atomic_t        skc_refcnt;
  9. unsigned int        skc_hash;
  10. struct proto        *skc_prot;
  11. };

struct inet_sock。 
    这是INET域专用的一个socket表示,它是在struct sock的基础上进行的扩展,在基本socket的属性已具备的基础上,struct inet_sock提供了INET域专有的一些属性,比如TTL,组播列表,IP地址,端口等,下面是其完整定义:

  1. struct inet_sock {
  2. struct sock     sk;
  3. #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
  4. struct ipv6_pinfo   *pinet6;
  5. #endif
  6. __u32           daddr;          //IPv4的目的地址。
  7. __u32           rcv_saddr;      //IPv4的本地接收地址。
  8. __u16           dport;          //目的端口。
  9. __u16           num;            //本地端口(主机字节序)。
  10. __u32           saddr;          //发送地址。
  11. __s16           uc_ttl;         //单播的ttl。
  12. __u16           cmsg_flags;
  13. struct ip_options   *opt;
  14. __u16           sport;          //源端口。
  15. __u16           id;             //单调递增的一个值,用于赋给iphdr的id域。
  16. __u8            tos;            //服务类型。
  17. __u8            mc_ttl;         //组播的ttl
  18. __u8            pmtudisc;
  19. __u8            recverr:1,
  20. is_icsk:1,
  21. freebind:1,
  22. hdrincl:1,      //是否自己构建ip首部(用于raw协议)
  23. mc_loop:1;      //组播是否发向回路。
  24. int             mc_index;       //组播使用的本地设备接口的索引。
  25. __u32           mc_addr;        //组播源地址。
  26. struct ip_mc_socklist   *mc_list;   //组播组列表。
  27. struct {
  28. unsigned int        flags;
  29. unsigned int        fragsize;
  30. struct ip_options   *opt;
  31. struct rtable       *rt;
  32. int                 length;
  33. u32                 addr;
  34. struct flowi        fl;
  35. } cork;
  36. };

struct raw_sock 
    这是RAW协议专用的一个socket的表示,它是在struct inet_sock基础上的扩展,因为RAW协议要处理ICMP协议的过滤设置,其定义如下:

  1. struct raw_sock {
  2. struct inet_sock   inet;
  3. struct icmp_filter filter;
  4. };

struct udp_sock 
    这是UDP协议专用的一个socket表示,它是在struct inet_sock基础上的扩展,其定义如下:

  1. struct udp_sock {
  2. struct inet_sock inet;
  3. int             pending;
  4. unsigned int    corkflag;
  5. __u16           encap_type;
  6. __u16           len;
  7. };

struct inet_connection_sock 
    看完上面两个,我们觉得第三个应该就是struct tcp_sock了,但事实上,struct tcp_sock并不直接从struct inet_sock上扩展,而是从struct inet_connection_sock基础上进行扩展,struct inet_connection_sock是所有面向连接的socket的表示,关于该socket,及下面所有tcp相关的socket,我们在分析 tcp实现时再详细介绍,这里只列出它们的关系。

strcut tcp_sock 
    这是TCP协议专用的一个socket表示,它是在struct inet_connection_sock基础进行扩展,主要是增加了滑动窗口协议,避免拥塞算法等一些TCP专有属性。

struct inet_timewait_sock

struct tcp_timewait_sock 
    在struct inet_timewait_sock的基础上进行扩展。

struct inet_request_sock

struct tcp_request_sock 
    在struct inet_request_sock的基础上进行扩展。

Struct Socket详细分析(转)的更多相关文章

  1. linux内核中socket的创建过程源码分析(详细分析)

    1三个相关数据结构. 关于socket的创建,首先需要分析socket这个结构体,这是整个的核心. 104 struct socket { 105         socket_state       ...

  2. struct socket 结构详解

    Socket数据结构网络协议CC++     用户使用socket系统调用编写应用程序时,通过一个数字来表示一个socket,所有的操作都在该数字上进行,这个数字称为套接字描述符.在系统调用 的实现函 ...

  3. 海思uboot启动流程详细分析(三)【转】

    1. 前言 书接上文(u-boot启动流程分析(二)_平台相关部分),本文介绍u-boot启动流程中和具体版型(board)有关的部分,也即board_init_f/board_init_r所代表的. ...

  4. 内核中container_of宏的详细分析【转】

    转自:http://blog.chinaunix.net/uid-30254565-id-5637597.html 内核中container_of宏的详细分析 16年2月28日09:00:37 内核中 ...

  5. Linux内核TCP MSS机制详细分析

    前言 上周Linux内核修复了4个CVE漏洞[1],其中的CVE-2019-11477感觉是一个很厉害的Dos漏洞,不过因为有其他事打断,所以进展的速度比较慢,这期间网上已经有相关的分析文章了.[2] ...

  6. PE头详细分析

    目录 PE头详细分析 0x00 前言 0x01 PE文件介绍 0x02 PE头详细分析 DOS头解析 NT头解析 标准PE头解析 可选PE头解析 可选PE头结构 基址 代码段地址 数据段地址 OEP程 ...

  7. PE节表详细分析

    目录 PE节表详细分析 0x00 前言 0x01 PE节表分析 节表结构 节表数量 节表名字 节表大小 节位置 节表属性 0x02 代码编写 PE节表详细分析 0x00 前言 上一篇文章我们学习了PE ...

  8. ZIP压缩算法详细分析及解压实例解释

    最近自己实现了一个ZIP压缩数据的解压程序,觉得有必要把ZIP压缩格式进行一下详细总结,数据压缩是一门通信原理和计算机科学都会涉及到的学科,在通信原理中,一般称为信源编码,在计算机科学里,一般称为数据 ...

  9. 1125MySQL Sending data导致查询很慢的问题详细分析

    -- 问题1 tablename使用主键索引反而比idx_ref_id慢的原因EXPLAIN SELECT SQL_NO_CACHE COUNT(id) FROM dbname.tbname FORC ...

随机推荐

  1. windowsServer-------- 系统中调出文件扩展名

    Windows Server是微软发布的一系列服务器操作系统的品牌名. 各个品牌的发布日期 Windows Server 2003 (2003年4月) Windows Server 2003 R2(2 ...

  2. [转帖]java注解核心知识总结

    java注解核心知识总结 2019-11-01 20:39:50 从事Java 阅读数 2  收藏 文章标签: java注解总结程序员 更多 分类专栏: java 注解   版权声明:本文为博主原创文 ...

  3. 25个强大的CSS代码,据说这些是开发者经常遇到比较棘手的代码

    这些代码是经常用到的,比方说一些特殊的效果,圆角边框,CSS透明度,梯形环绕,CSS小三角等,希望对你有用 1简单又好的 Blockquote 样式 CSS代码如下 blockquote { back ...

  4. memcached源码分析一-slab

    Slab作为一种内存管理方案,其作用主要有以下2点: a) 避免频繁的内存分配释放造成的内存碎片 b) 减少内存分配操作产生的性能开销 Linux内核数据结构中也有slab的设计,Linux提供了一套 ...

  5. c# Windows服务管理

    .NET Framework中提供的类库可以很方便的实现对windows服务的安装.卸载.启动.停止.获取运行状态等功能.这些类都在System.ServiceProcess命名空间下. 所以,在开始 ...

  6. 不用Pageant告别Pageant Windows10下TortoiseGit和Git配置使用同一SSH密钥

    关于Git使用SSH免密连接参考:https://blog.csdn.net/qq_32786873/article/details/80570788 关于Windows10下TortoiseGit使 ...

  7. 论文翻译:Data mining with big data

    原文: Wu X, Zhu X, Wu G Q, et al. Data mining with big data[J]. IEEE transactions on knowledge and dat ...

  8. JavaScript 书写位置

    类似于 CSS 样式,JavaScript 也有三种不同位置的书写方式. 1.写在行内 <input type="button" value="按钮" o ...

  9. Sping注解开发

    基本注解 @Configuration 作用: 标记在类上表示是一个配置类(相当于一个配置类) @Bean 作用: 在容器中放一个bean相当于xml文件里的bean标签 @Configuration ...

  10. openssl生成证书及签名

    第一步,生成私钥 $ openssl genrsa -out privatekey.pem 2048 查看生成的私钥内容 $ file privatekey.pem privatekey.pem: P ...