TCP/IP工作流的开始 socket创建4
2016-12-25 22:01
393 查看
tcp_v4_init_sock函数的剩下部分
继续回到tcp_v4_init_sock。1873 tp->reordering = sysctl_tcp_reordering;
又是struct tcp_sock的一个成员变量reordering,意思为重新排序。这里只是设置一个初值,其具体含义,现在还不知道。从数值来源变量名称中,可以看到这个是可以通过用户来控制的一个选项。1874 icsk->icsk_ca_ops = &tcp_init_congestion_ops;
这个变量tcp_init_congestion_ops看起来有点熟悉,之前在tcp_init函数(见TCP/IP协议栈初始化(八) TCP马上准备进入状态 )中说过,当时是注册了一个tcp_reno的变量。从名称上来看2个都是用来实现TCP拥堵控制的。两个变量都是在net/ipv4/tcp_cong.c中定义,相邻。376 struct tcp_congestion_ops tcp_reno = { 377 .flags = TCP_CONG_NON_RESTRICTED, 378 .name = "reno", 379 .owner = THIS_MODULE, 380 .ssthresh = tcp_reno_ssthresh, 381 .cong_avoid = tcp_reno_cong_avoid, 382 .min_cwnd = tcp_reno_min_cwnd, 383 }; 389 struct tcp_congestion_ops tcp_init_congestion_ops = { 390 .name = "", 391 .owner = THIS_MODULE, 392 .ssthresh = tcp_reno_ssthresh, 393 .cong_avoid = tcp_reno_cong_avoid, 394 .min_cwnd = tcp_reno_min_cwnd, 395 };
仔细一看,原来所有的变量成员都一样。这:<
1876 sk->sk_state = TCP_CLOSE;
设置TCP连接的状态是TCP_CLOSE,因为socket的创建流程还没有进行完毕。1878 sk->sk_write_space = sk_stream_write_space;
1879 sock_set_flag(sk, SOCK_USE_WRITE_QUEUE);
初始化了struct sock的写空间回调函数,TCP执行流量控制,不可能用户产生多少数据都能快速发送出去,所以这里为sock配置了写队列,并且给它添加了回调函数,当队列中有空间时,就可以通知用户继续写入数据。并设置了struct sock *sk要使用写队列。1881 icsk->icsk_af_ops = &ipv4_specific;
1882 icsk->icsk_sync_mss = tcp_sync_mss;
设置socket关联的struct inet_connetion_sock的成员变量icsk_af_ops。同样af是代表address family。与地址协议族相关的调用接口。这里被初始化为ipv4_specific。这个变量定义在net/ipv4/tcp_ipv4.c中。其成员函数,现在还没有遇到。先不说。1882初始化的成员变量是,用来在连接建立时同步MSS。MSS就是最大报文段长度,是MTU减去IP层和TCP首部后的长度。
1883-1885 是允许编译内核时,由TCP层来计算校验各。这里不展开说。
1887 sk->sk_sndbuf = sysctl_tcp_wmem[1];
1888 sk->sk_rcvbuf = sysctl_tcp_rmem[1];
初始化每个sk的接收缓存和发送缓存区的大小。赋以的初值正是在TCP初始化时的遇到的sysctl_tcp_[w/r]mem数组。不知道为什么用的是每个数组的第2个值。这个值是允许用户去修改的。如果用心没有修改的话,默认的就是16KB和85KB。感兴趣的可以去系统/proc/sys/net/ipv4/下看下,可以看到两个文件,每个文件只有一行,三列的数据。中间的数值就是上面sk->sk_sndbuf和sk->sk_rcvbuf的值。
lin@linp:/proc/sys/net/ipv4$ ls tcp_[wr]mem tcp_rmem tcp_wmem lin@linp:/proc/sys/net/ipv4$ cat tcp_rmem;cat tcp_wmem 4096 87380 6108448 4096 16384 4194304
1890 atomic_inc(&tcp_sockets_allocated);
最后一个语句。增加了一个变量的值。从变量的名称就能看出,这个是记录系统分配了多少个TCP socket。tcp_v4_init_sock返回
tcp_v4_init_sock函数执行完毕了。函数依次返回到inet_create,__sock_create,sock_create, sys_socket中。返回后,下面还有一个重要的函数要提,就是sock_map_fd。因为这个函数会把生成的struct socket *sock映射为一个文件ID,就是int类型的变量。让用户通过这个ID来调用socket。为什么要这样做呢?这是unix系统里的宗旨,“一切皆文件”,向用户提供一致的易用的接口。
1211 retval = sock_map_fd(sock);
sock_map_fd(sock);
同样定义在net/socket.c中。394 int sock_map_fd(struct socket *sock) 395 { 396 struct file *newfile; 397 int fd = sock_alloc_fd(&newfile); 399 if (likely(fd >= 0)) { 400 int err = sock_attach_fd(sock, newfile); 402 if (unlikely(err < 0)) { 403 put_filp(newfile); 404 put_unused_fd(fd); 405 return err; 406 } 407 fd_install(fd, newfile); 408 } 409 return fd; 410 }
396 struct file *newfile;
396 定义了一个文件指针变量。这里的file仍然是内核里面的数据类型。397 int fd = sock_alloc_fd(&newfile);
把指针的地址传入sock_alloc_fd,为其分配一个file类型的变量。并返回一个没有使用的文件ID。这个函数不负责ID和file变量之间的关联。400 int err = sock_attach_fd(sock, newfile);
把sock和新分配的文件指针关联起来。sock_attach_fd同样是在net/socket.c中定义。关联的步骤为:1. 370 从socket超级块中分配一个目录entry。
2. 374-381 按照socket文件系统要求初始化这个entry。
3. 383 把sock的文件指针指向要关联的文件,完成关联。
4. 384-389 初始化文件一些属性。把file的private_data(类型为void*)指向sock。对应的文件操作函数集合为socket_file_ops。
365 static int sock_attach_fd(struct socket *sock, struct file *file) 366 { 367 struct dentry *dentry; 368 struct qstr name = { .name = "" }; 370 dentry = d_alloc(sock_mnt->mnt_sb->s_root, &name); 371 if (unlikely(!dentry)) 372 return -ENOMEM; 374 dentry->d_op = &sockfs_dentry_operations; 380 dentry->d_flags &= ~DCACHE_UNHASHED; 381 d_instantiate(dentry, SOCK_INODE(sock)); 383 sock->file = file; 384 init_file(file, sock_mnt, dentry, FMODE_READ | FMODE_WRITE, 385 &socket_file_ops); 386 SOCK_INODE(sock)->i_fop = &socket_file_ops; 387 file->f_flags = O_RDWR; 388 file->f_pos = 0; 389 file->private_data = sock; 391 return 0; 392 }
回到sock_map_fd中。
407 fd_install(fd, newfile);
前面文件的关联都没有问题了。这时可以把文件ID fd和新生成的文件指针 newfile指向的文件关联起来了。具体的关系过程涉及到进程的文件管理,比较复杂。不多说了。此时,sys_socket也执行完成了。socket创建也就完成了,返回的ID值就是以后用来引用socket的值。
相关文章推荐
- TCP/IP工作流的开始 socket创建3
- TCP/IP工作流的开始 socket创建2
- TCP/IP工作流的开始 socket创建 1
- VBSocket编程(Winsock控件创建TCP/IP客户机/服务器程序)
- TCP/IP工作流5 connect开始
- TCP/IP、Http、Socket的区别
- 关于tcp 创建用来listen的socket时使用的地址
- JAVA TCP/IP Socket通信机制以及应用
- Java TCPIP 编程 那些事 ServerSocket (一)
- java--TCP,IP,HTTP,SOCKET区别和联系
- 一篇文章看明白 TCP/IP,TCP,UDP,IP,Socket 之间的关系
- TCP/IP、Http、Socket的区别
- Http TCP/IP UDP socket 解析
- TCP/IP、Http、Socket的区别
- tcp ip 通信socket
- TCP/IP、Http、Socket的区别
- TCP/IP、Http、Socket的区别
- ip,TCP,UDP,HTTP,TCP/IP,SOCKET
- TCP/IP、UDP、HTTP、Socket到底是什么
- TCP/IP Socket Communications in MATLAB example