tcp 多线程与多进程调用close

http://blog.csdn.net/russell_tao/article/details/13092727

大家知道,所谓线程其实就是“轻量级”的进程。创建进程只能是一个进程(父进程)创建另一个进程(子进程),子进程会复制父进程的资源,这里的”复制“针对不同的资源其意义是不同的,例如对内存、文件、TCP连接等。创建进程是由clone系统调用实现的,而创建线程时同样也是clone实现的,只不过clone的参数不同,其行为也很不同。这个话题是很大的,这里我们仅讨论下TCP连接。
在clone系统调用中,会调用方法copy_files来拷贝文件描述符(包括socket)。创建线程时,传入的flag参数中包含标志位CLONE_FILES,此时,线程将会共享父进程中的文件描述符。而创建进程时没有这个标志位,这时,会把进程打开的所有文件描述符的引用计数加1,即把file数据结构的f_count成员加1,如下:
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. static int copy_files(unsigned long clone_flags, struct task_struct * tsk)  
  2. {  
  3.     if (clone_flags & CLONE_FILES) {  
  4.         goto out;//创建线程  
  5.     }  
  6.     newf = dup_fd(oldf, &error);  
  7. out:  
  8.     return error;  
  9. }  

再看看dup_fd方法:
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. static struct files_struct *dup_fd(struct files_struct *oldf, int *errorp)  
  2. {  
  3.     for (i = open_files; i != 0; i--) {  
  4.         struct file *f = *old_fds++;  
  5.         if (f) {  
  6.             get_file(f);//创建进程  
  7.         }  
  8.     }  
  9. }  

get_file宏就会加引用计数。
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. #define get_file(x) atomic_inc(&(x)->f_count)  

所以,子进程会将父进程中已经建立的socket加上引用计数。当进程中close一个socket时,只会减少引用计数,仅当引用计数为0时才会触发tcp_close。
 
到这里,对于第一个问题的close调用自然有了结论:单线程(进程)中使用close与多线程中是一致的,但这两者与多进程的行为并不一致,多进程中共享的同一个socket必须都调用了close才会真正的关闭连接。
 
而shutdown则不然,这里是没有引用计数什么事的,只要调用了就会去试图按需关闭连接。所以,调用shutdown与多线程、多进程无关。
原文地址:https://www.cnblogs.com/diegodu/p/4705806.html