免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1523 | 回复: 0
打印 上一主题 下一主题

Linux2.6.30内核的sock结构(3)-1/5 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-11-18 11:28 |只看该作者 |倒序浏览

Linux2.6.30内核的sock结构
978计划工作组 2009-11-18
1函数源码
struct sock {
       /*
        * Now struct inet_timewait_sock also uses sock_common, so please just
        * don't add nothing before this first member (__sk_common) --acme
        */
       struct sock_common     __sk_common;
#define sk_family          __sk_common.skc_family
#define sk_state            __sk_common.skc_state
#define sk_reuse           __sk_common.skc_reuse
#define sk_bound_dev_if              __sk_common.skc_bound_dev_if
#define sk_node                   __sk_common.skc_node
#define sk_nulls_node           __sk_common.skc_nulls_node
#define sk_bind_node           __sk_common.skc_bind_node
#define sk_refcnt          __sk_common.skc_refcnt
#define sk_hash                   __sk_common.skc_hash
#define sk_prot                    __sk_common.skc_prot
#define sk_net               __sk_common.skc_net
       unsigned char        sk_shutdown : 2,
                            sk_no_check : 2,
                            sk_userlocks : 4;
       unsigned char        sk_protocol;
       unsigned short              sk_type;
       int                  sk_rcvbuf;
       socket_lock_t        sk_lock;
       /*
        * The backlog queue is special, it is always used with
        * the per-socket spinlock held and requires low latency
        * access. Therefore we special case it's implementation.
        */
       struct {
              struct sk_buff *head;
              struct sk_buff *tail;
       } sk_backlog;
       wait_queue_head_t *sk_sleep;
       struct dst_entry      *sk_dst_cache;
#ifdef CONFIG_XFRM
       struct xfrm_policy  *sk_policy[2];
#endif
       rwlock_t        sk_dst_lock;
       atomic_t         sk_rmem_alloc;
       atomic_t         sk_wmem_alloc;
       atomic_t         sk_omem_alloc;
       int                  sk_sndbuf;
       struct sk_buff_head       sk_receive_queue;
       struct sk_buff_head       sk_write_queue;
#ifdef CONFIG_NET_DMA
       struct sk_buff_head       sk_async_wait_queue;
#endif
       int                  sk_wmem_queued;
       int                  sk_forward_alloc;
       gfp_t                     sk_allocation;
       int                  sk_route_caps;
       int                  sk_gso_type;
       unsigned int           sk_gso_max_size;
       int                  sk_rcvlowat;
       unsigned long               sk_flags;
       unsigned long          sk_lingertime;
       struct sk_buff_head       sk_error_queue;
       struct proto           *sk_prot_creator;
       rwlock_t        sk_callback_lock;
       int                  sk_err,
                            sk_err_soft;
       atomic_t         sk_drops;
       unsigned short              sk_ack_backlog;
       unsigned short              sk_max_ack_backlog;
       __u32                   sk_priority;
       struct ucred           sk_peercred;
       long               sk_rcvtimeo;
       long               sk_sndtimeo;
       struct sk_filter          *sk_filter;
       void               *sk_protinfo;
       struct timer_list      sk_timer;
       ktime_t                  sk_stamp;
       struct socket          *sk_socket;
       void               *sk_user_data;
       struct page            *sk_sndmsg_page;
       struct sk_buff        *sk_send_head;
       __u32                   sk_sndmsg_off;
       int                  sk_write_pending;
#ifdef CONFIG_SECURITY
       void               *sk_security;
#endif
       __u32                   sk_mark;
       /* XXX 4 bytes hole on 64 bit */
       void               (*sk_state_change)(struct sock *sk);
       void               (*sk_data_ready)(struct sock *sk, int bytes);
       void               (*sk_write_space)(struct sock *sk);
       void               (*sk_error_report)(struct sock *sk);
      int                  (*sk_backlog_rcv)(struct sock *sk,
                                            struct sk_buff *skb);  
       void                    (*sk_destruct)(struct sock *sk);
};
2结构用途
    sock结构是对socket结构的扩充,与文件系统相关的域放在socket结构中了,而与网络相关的域放在了sock结构中了,目的是在非网络数据结构中定义socket域时无需包括整个sock结构,而只分配一个sock结构的指针即可,这样可以大大的节约内存。
3语句注释
3.1 成员注释
struct sock_common      __sk_common
       网络层的最常用属性放在此结构中了,如地址族、连接状态等。详细信息参见sock_common结构。
unsigned char   sk_shutdown : 2
       标示了socket关闭的情况,关于关闭的情况有3种,如下所示:
    SHUTDOWN_MASK:宏值为3,表示完全关闭。
    RCV_SHUTDOWN:宏值为1 :接收通道被关闭(远端发送了FIN 数据包)。
SEND_SHUTDOWN:发送通道关闭(本地主动发送FIN 数据包)。
unsigned char   sk_no_check : 2
       打开或关闭校验和。
unsigned char   sk_userlocks : 4
       用户锁标志,有四种锁,共占四位,如下所示:
SOCK_SNDBUF_LOCK  :宏值为1,sk_userlocks的第0位(最低位为0位)为1时不可以修改sk_sndbuf的值,即如果锁了就不可以修改此值。
SOCK_RCVBUF_LOCK :宏值为2,sk_userlocks的第1位(最低位为0位)为1时不可以修改sk_rcvbuf的值,即如果锁了就不可以修改此值。
SOCK_BINDADDR_LOCK  :宏值为4,sk_userlocks域在inet_bind函数中将第2位(最低位为0位)置位1,此位被置位后不可再调用inet_reset_saddr函数重新设置地址。
SOCK_BINDPORT_LOCK :宏值为8,sk_userlocks域在inet_bind函数中将第3位(最低位为0位)置位1,该位被置位后不可调用inet_put_port函数。
unsigned char   sk_protocol
       标示使用哪种协议,此域在inet_create中被初始化。
unsigned short sk_type
       socket的类型,有7种类型,如下所示:
SOCK_STREAM:值为1,流套接字,提供双向连续且可信赖的数据流,TCP协议用此种类型。SOCK_DGRAM:值为2,数据报套接字,使用不连续不可信赖的数据包连接,UDP协议用此种类
型。
SOCK_RAW:值为3,原始套接字,一般的套接字是通过TCP才能和IP底层进行数据交换的,原始套接字可以直接穿过TCP层操作IP数据包,也就是说原始套接字是上层应用程序和IP层之间的通道。
SOCK_RDM:值为4,提供可信赖的数据包连接。
SOCK_SEQPACKET:值为5,顺序包套接字, 提供连续可信赖的数据包连接。
SOCK_DCCP:值为6,数据报阻塞控制协议套接字。
SOCK_PACKET:值为10,提供和网络驱动程序直接通信,Linux特有的方式。
还有一个特殊的宏,标示socket类型的上限值的宏SOCK_MAX,被定义为 (SOCK_PACKET + 1)。
Int   sk_rcvbuf
       以字节为单位的接收缓冲区的大小。
socket_lock_t    sk_lock
       sock的同步锁。
struct {
              struct sk_buff *head;
              struct sk_buff *tail;
} sk_backlog
       sk_backlog链表中数据的处理的函数调用关系是:
tcp_recvmsg调用release_sock,release_sock调用__release_sock,__release_sock调用sk_backlog_rcv,而sk_backlog_rcv函数指针指向了tcp_v4_do_rcv,详情参见下面对sk_backlog_rcv的介绍,tcp_v4_do_rcv函数在TCP_ESTABLISHED状态时通过调用tcp_rcv_established函数实现数据处理并释放了节点。在TCP_LISTEN状态时会调用tcp_child_process。
sk_backlog链表中的数据被增加的函数调用关系是:
ip层接到数据包处理完后是通过ip_local_deliver函数把ip包递送到上层进行处理的(具体的Ip层及以下层是如何处理的在其他文档中讨论),ip_local_deliver函数调用ip_local_deliver_finish函数,ip_local_deliver_finish函数中通过全局的struct net_protocol的实例inet_protos[hash]取得struct net_protocol的指针。
inet_protos[hash]的handler域是一个函数指针指向了tcp_v4_rcv函数;系统中存在一个全局静态struct net_protocol结构的实例tcp_protocol,此实例的handler域被tcp_v4_rcv初始化,在inet_init函数中将此静态实例tcp_protocol通过inet_add_protocol付给了hash表结构的数组inet_protos,这样inet_protos[hash]->handler域就指向了tcp_v4_rcv。
tcp_v4_rcv函数在需要将数据放到sk_backlog对列时通过直接调用sk_add_backlog函数实现了将收到的数据增加到sk_backlog链表中,或者通过调用tcp_v4_do_rcv函数,tcp_v4_do_rcv在TCP_LISTEN状态时可能会调用tcp_child_process ,而tcp_child_process 再调用sk_add_backlog函数间接实现将收到的数据添加到sk_backlog链表中。
wait_queue_head_t *sk_sleep
       等待队列,主要应用在客户端发起连接后等待连接完成,以及服务器端的accept函数等待新连接建立的完成。主要在rfcomm_sock_accept、sco_sock_accept、inet_wait_for_connect等函数中使用。


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/100948/showart_2097388.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP