赞
踩
前言
笔者一直觉得如果能知道从应用到框架再到操作系统的每一处代码,是一件Exciting的事情。
今天笔者就来从Linux源码的角度看下Client端的Socket在进行Connect的时候到底做了哪些事情。由于篇幅原因,关于Server端的Accept源码讲解留给下次给大家介绍。
(基于Linux 3.10内核)
一个最简单的Connect例子
int clientSocket;
if((clientSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
// 创建socket失败失败
return -1;
}
......
if(connect(clientSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0) {
// connect 失败
return -1;
}
.......
首先我们通过socket系统调用创建了一个socket,其中指定了SOCK_STREAM,而且最后一个参数为0,也就是建立了一个通常所有的TCP Socket。在这里,我们直接给出TCP Socket所对应的ops也就是操作函数。
如果你想知道上图中的结构是怎么来的,可以看下笔者以前的文章:
值得注意的是,由于socket系统调用操作做了如下两个代码的判断
sock_map_fd
|->get_unused_fd_flags
|->alloc_fd
|->expand_files (ulimit)
|->sock_alloc_file
|->alloc_file
|->get_empty_filp (/proc/sys/fs/max_files)
第一个判断,ulmit超限:
int expand_files(struct files_struct *files, int nr
{
......
if (nr >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
return -EMFILE;
......
}
这边的判断即是ulimit的限制!在这里返回-EMFILE对应的描述就是
"Too many open files"
第二个判断max_files超限
struct file *get_empty_filp(void)
{
......
/*
* 由此可见,特权用户可以无视文件数最大大小的限制!
*/
if (get_nr_files() >= files_stat.max_files && !capable(CAP_SYS_ADMIN)) {
/*
* percpu_counters are inaccurate. Do an expensive check before
* we go and fail.
*/
if (percpu_counter_sum_positive(&nr_files) >= files_stat.max_files)
goto over;
}
......
}
所以在文件描述符超过所有进程能打开的最大文件数量限制(/proc/sys/fs/file-max)的时候会返回-ENFILE,对应的描述就是"Too many open files in system",但是特权用户确可以无视这一限制,如下图所示:
connect系统调用
我们再来看一下connect系统调用:
int connect(int sockfd,const struct sockaddr *serv_addr,socklen_t addrlen)
这个系统调用有三个参数,那么依据规则,它肯定在内核中的源码长下面这个样子
SYSCALL_DEFINE3(connect, ......
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。