ImageVerifierCode 换一换
格式:DOCX , 页数:23 ,大小:29.62KB ,
资源ID:18636055      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/18636055.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(linux内核中socket的实现Word格式文档下载.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

linux内核中socket的实现Word格式文档下载.docx

1、31 sys_getsockname(a0, (struct sockaddr _user *)a1, 32 (int _user *)a2);33 break;34 . 35 return err;36 可以看到代码比较简单,就是通过传递进来的call类型,来调用相应的socket相关的函数. 这里你可能注意到了,那就是一般文件句柄相关的操作,比如write,read,aio,poll这些并没有看到(也就是file_operations).这是因为socket上面其实还有一层vfs层,内核把socket当做一个文件系统来处理,并实现了相应的vfs方法.因此下面我们先来了解下vfs.然后会描述

2、下进程如何通过vfs存取句柄. vfs其实就相当于对下层的文件系统和上层应用之间的粘合层,它定义了文件系统需要实现的相关的操作,然后下层的文件系统只需要实现这些方法就可以了,也就是说在内核其他部分和上层应用看来,所有的文件系统没有任何区别. 下面的这张图就是从用户空间调用write的大体流程:vfs中有4种主要的数据结构:1 超级块对象,代表一个已安装的文件系统.super_block 2 索引节点对象,代表一个文件.inode 3 目录项对象,代表一个目录项.dentry 4 文件对象,表示一个被进程打开的文件.file 其中每种对象都包含一个操作对象.依次为super_operations

3、,inode_operations,dentry_operations以及file_operations.各自操作不同的层次.然后我们的文件系统只需要实现这些方法,然后注册到内核就可以了. 接下来我们来看和vfs相应的结构:第一个就是file_system_type结构,这个结构表示了一个文件系统:37 struct file_system_type 38 const char *name;39 int fs_flags;40 /最关键的函数,得到文件系统的超级块. 41 int (*get_sb) (struct file_system_type *, int, 42 const char

4、*, void *, struct vfsmount *);43 void (*kill_sb) (struct super_block *);44 . 45 ;然后是vfsmount结构,它表示了一个安装点,换句话说也就是一个文件系统实例. 第三个是files_struct结构,它主要是为每个进程来维护它所打开的句柄.这里只需要注意一个就是fd_array和fstable中的fd的区别.当进程数比较少也就是小于NR_OPEN_DEFAULT(32)时,句柄就会存放在fd_array中,而当句柄数超过32则就会重新分配数组,然后将fd指针指向它(然后我们通过fd就可以取得相应的file结构).

5、 而且files_struct是每个进程只有一个的. 46 struct files_struct 47 /* 48 * read mostly part 49 */ 50 atomic_t count;51 struct fdtable *fdt;52 struct fdtable fdtab;53 /* 54 * written part on a separate cache line in SMP 55 */ 56 spinlock_t file_lock _cacheline_aligned_in_smp;57 int next_fd;58 struct embedded_fd_se

6、t close_on_exec_init;59 struct embedded_fd_set open_fds_init;60 /所打开的所有文件 61 struct file * fd_arrayNR_OPEN_DEFAULT;62 ;63 64 65 struct fdtable 66 unsigned int max_fds;67 struct file * fd; /* current fd array */ 68 fd_set *close_on_exec;69 fd_set *open_fds;70 struct rcu_head rcu;71 struct fdtable *ne

7、xt;72 ;还有两个一个是fs_struct,一个是namespace也都是进程相关的.这里就不一一介绍了. 我这里vfs介绍只是个大概,需要详细了解的,可以去看ulk的vfs相关章节和linux内核设计与实现的相关章节. 因此下面的图表示了进程和socket的关系:上面的这张图有些老了,新的内核中的inode节点中已经没有u这个联合体了,对应的是会有一个包含socket和inode的一个结构体,然后我们通过inode,而inode中专门有个i_mode域来判断相应的inode类型,比如socket就是 S_IFSOCK.就可以直接计算出相应的socket的地址,然后就可以存取socket了

8、.后面我们会介绍. 内核中标售socket有两个数据结构,一个是socket,另一个是sock,其中socket是一个general BSD socket, 它也就是应用程序和4层协议之间的一个接口,屏蔽掉了相关的4层协议部分.而在内核中,socket所需要使用的相关的4层协议的信息全部是保存在sock结构当中的,而socket和sock这两个结构都有保存对方的指针,因此可以很容易的存取对方. 还有一个就是ops域,这个域保存了所有的相关的4层协议的操作函数. 而在sock中有一个sk_common保存了一个skc_prot域,这个域保存的是相应的协议簇的操作函数的集合. 后面介绍到socke

9、t创建的时候,我们会分析proto_ops和proto的区别.其实proto相当于对proto_ops的一层封装,最终会在proto中调用proto_ops. 73 /* 74 * struct socket - general BSD socket 75 * state: socket state (%SS_CONNECTED, etc) 76 * type: socket type (%SOCK_STREAM, etc) 77 * flags: socket flags (%SOCK_ASYNC_NOSPACE, etc) 78 * ops: protocol specific socke

10、t operations 79 * fasync_list: Asynchronous wake up list 80 * file: File back pointer for gc 81 * sk: internal networking protocol agnostic socket representation 82 * wait: wait queue for several uses 83 */ 84 struct socket 85 socket_state state;86 short type;87 unsigned long flags;88 const struct p

11、roto_ops *ops;89 struct fasync_struct *fasync_list;90 struct file *file;91 struct sock *sk;92 wait_queue_head_t wait;93 ;94 95 struct sock_common 96 unsigned short skc_family;97 volatile unsigned char skc_state;98 unsigned char skc_reuse;99 int skc_bound_dev_if;100 struct hlist_node skc_node;101 str

12、uct hlist_node skc_bind_node;102 atomic_t skc_refcnt;103 unsigned int skc_hash;104 struct proto *skc_prot;105 #ifdef CONFIG_NET_NS 106 struct net *skc_net;107 #endif 108 ;109 110 struct proto_ops 111 int family;112 struct module *owner;113 int (*release) (struct socket *sock);114 int (*bind) (struct

13、 socket *sock, 115 struct sockaddr *myaddr, 116 int sockaddr_len);117 int (*connect) (struct socket *sock, 118 struct sockaddr *vaddr, 119 int sockaddr_len, int flags);120 . 121 ;然后我们来看sock_init的实现,在这个函数中,将socket注册为一个伪文件系统,并安装相应的mount点:122 /相应的mount对象 123 static struct vfsmount *sock_mnt _read_mostl

14、y;124 /文件系统对象. 125 static struct file_system_type sock_fs_type = 126 .name = sockfs, 127 .get_sb = sockfs_get_sb, 128 .kill_sb = kill_anon_super, 129 ;130 131 static int _init sock_init(void) 132 133 /* 134 * Initialize sock SLAB cache. 135 */ 136 137 sk_init();138 139 /* 140 * Initialize skbuff SLA

15、B cache 141 */ 142 skb_init();143 144 /初始化一个inodecache. 145 init_inodecache();146 /注册文件系统到内核. 147 register_filesystem(&sock_fs_type);148 /安装mount点. 149 sock_mnt = kern_mount(&150 151 #ifdef CONFIG_NETFILTER 152 netfilter_init();153 #endif 154 return 0;155 我们知道每次创建一个socket,都是要依赖于当前的protocol family类型的

16、(后面会分析sys_socket的源码的时候会看到).而在内核中,每种类型的protocol family都会有一个相对应的net_proto_family结构,然后将这个结构注册到内核的net_families数组中,这样我们创建socket的时候,就可以调用这个数组来创建socket. 我们先来看sock_register的源码,也就是如何将一个net_proto_family注册到相应的数组:156 static const struct net_proto_family *net_familiesNPROTO _read_mostly;157 158 int sock_register

17、(const struct net_proto_family *ops) 159 160 int err;161 162 if (ops-family = NPROTO) 163 printk(KERN_CRIT protocol %d = NPROTO(%d)n, ops-family, 164 NPROTO);165 return -ENOBUFS;166 167 168 spin_lock(&net_family_lock);169 /代码非常简单,就是根据类型,然后放到相应的位置. 170 if (net_familiesops-family) 171 err = -EEXIST;17

18、2 else 173 net_familiesops-family = ops;174 err = 0;175 176 spin_unlock(&177 178 printk(KERN_INFO NET: Registered protocol family %dnfamily);179 return err;180 我们知道每个协议簇和相应的套接口都对应有好多种组合,因此在协议簇的实现中保存了一个相应的结构来保存这些组合,然后后面就首先通过family然后确定到某个结构,再根据套接口的类型来得到这个结构,并赋值给sock. 这里要注意我们只分析af_inet的实现,其他的协议簇都差不多:我们

19、来看这个的实现:181 /可以看到这是一个数组,每个元素都是一个链表,也就是每种类型的socket就是一个链表.而这个链表所包含的是不同4层协议的inetsw.可是在inet中,现在每种类型的socket只对应一个4层协议.这里只是为了以后扩展. 182 static struct list_head inetswSOCK_MAX;183 184 /相应的socket的对应的信息的结构. 185 struct inet_protosw 186 struct list_head list;187 188 /需要这两个key才能定位一个inet_protosw. 189 unsigned shor

20、t type; /* This is the 2nd argument to socket(2). */ 190 unsigned short protocol; /* This is the L4 protocol number. */ 191 192 /相应的基于ipv4的4层协议的操作集合. 193 struct proto *prot;194 /相应的协议簇的操作信息. 195 const struct proto_ops *ops;196 197 int capability; /* Which (if any) capability do 198 * we need to use

21、this socket 199 * interface?200 */ 201 char no_check; /* checksum on rcv/xmit/none? */ 202 unsigned char flags; /* See INET_PROTOSW_* below. */ 203 ;204 205 void inet_register_protosw(struct inet_protosw *p) 206 207 struct list_head *lh;208 struct inet_protosw *answer;209 int protocol = p-protocol;2

22、10 struct list_head *last_perm;211 . 212 answer = NULL;213 last_perm = &inetswp-type;214 /这个操作也很简单,就是将inet_protosw根据套接口类型插入到全局链表数组. 215 list_for_each(lh, &type) 216 answer = list_entry(lh, struct inet_protosw, list);217 218 /* Check only the non-wild match. */ 219 if (INET_PROTOSW_PERMANENT & answer

23、-flags) 220 if (protocol = answer-protocol) 221 break;222 last_perm = lh;223 224 225 answer = NULL;226 227 if (answer) 228 goto out_permanent;229 /插入链表. 230 list_add_rcu(&p-list, last_perm);231 . 接下来来分析inet_init的源码. 232 /表示了所有的可能的当前协议簇和套接口类型的组合. 233 static struct inet_protosw inetsw_array = 234 235

24、236 .type = SOCK_STREAM, 237 .protocol = IPPROTO_TCP, 238 .prot = &tcp_prot, 239 .ops = &inet_stream_ops, 240 .capability = -1, 241 .no_check = 0, 242 .flags = INET_PROTOSW_PERMANENT | 243 INET_PROTOSW_ICSK, 244 , 245 246 247 .type = SOCK_DGRAM, 248 .protocol = IPPROTO_UDP, 249 .prot = &udp_prot, 25

25、0 .ops = &inet_dgram_ops, 251 .capability = -1, 252 .no_check = UDP_CSUM_DEFAULT, 253 .flags = INET_PROTOSW_PERMANENT, 254 , 255 256 257 258 .type = SOCK_RAW, 259 .protocol = IPPROTO_IP, /* wild card */ 260 .prot = &raw_prot, 261 .ops = &inet_sockraw_ops, 262 .capability = CAP_NET_RAW, 263 .no_check = UDP_CSUM_DEFAULT, 264 .flags = INET_PROTOSW_REUSE, 265 266 ;267 268 /协议簇的创建函数. 269 static struct net_proto_family inet_family_ops = 270 .family = PF_INET, 271 .create = inet_create, 272 .owner = THIS_MODULE, 273 ;274 275 static int _init inet_init(void) 276 277 .

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1