进程、线程、socket套接字-资源大小 & 切换代价

另,进程 & 线程的很多知识可以看这里:http://www.cnblogs.com/charlesblc/p/6135666.html

 

今天查了一下进程和线程的资源占用。

比如问:栈和堆的大小?

答:栈是线程的概念,堆是进程的概念。

线程栈的大小,通过 ulimit -s 来设定。Linux默认是10240,也就是10M,Windows默认是1M.

堆的大小,一般最大是 虚拟空间大小 - 1G内核空间大小 - 全局空间等部分,还跟寻址有关。

 

进程的大小,比线程,还多出了一个PCB(描述进程基本情况和运行状态),另外程序段,也是放在进程里的,线程保存的程序计数器、一组寄存器,和栈

 

socket套接字其实都是打开的文件句柄,只要文件句柄够用,socket套接字就够用。

虽然端口port只有65535,并且1024以下的还被保留了;但是socket是四元组,本地同一个端口可以对应远端多个IP和多个端口。

所以理论上这个四元组可以很多很多,网上有人说是 2的48次方。

 

更多的可以看《程序员的自我修养》。虽然我也不知道相关内容有没有。

 

切换代价

进程和线程的切换代价,一直是对比的重点。下面罗列一下:

进程间切换的步骤:

1,保存程序计数其以及其他寄存器。

2, 更新当前处于“运行态”的进程的进程控制块,把进程状态改为相应状态,更新其他相关域

3, 把被切换进程的进程控制块移到相关状态的队列

4, 选择另外一个进程开始执行,把该进程进程控制块的状态改为“运行态”

5, 恢复被选择进程的处理器在最近一次被切换出运行态时的上下文,比如载入程序计数器以及其他处理器的值。

进程间切换伴随着两次模式切换(用户--内核,内核--用户)。

 

(同一进程内)线程间切换的步骤:

线程分两种,用户级线程和内核级线程

在用户级线程中,

有关线程管理的所有工作都由应用程序完成,内核没有意识到线程的存在。

用户级线程间切换时,只需要保存用户寄存器的内容,程序计数器,栈指针,不需要模式切换。

缺点:

1, 在进程的某个线程执行系统调用时,不仅该线程被阻塞,该线程所在进程的所有线程都被阻塞

2, 无法利用多处理器

 

在内核级线程中,

有关线程的管理工作都是由内核完成的,应用程序部分没有线程管理的权限,只有一个接口(API)

内核级线程间切换时,除了保存上下文,还要进行模式切换。(看起来跟进程切换差不多,但不需要切换内存,缓存等,下面有详细描述)

优点:

1, 可以利用多处理器

2, 线程阻塞不会导致进程阻塞

 

这一篇,讲的更具体一些:http://blog.csdn.net/mba16c35/article/details/43382737

进程切换分两步
1.切换页目录以使用新的地址空间
2.切换内核栈和硬件上下文

 

对于linux来说,线程和进程的最大区别就在于地址空间。
对于线程切换,第1步是不需要做的,第2是进程和线程切换都要做的(但是仍然有不同,见下)。所以明显是进程切换代价大。

 

线程上下文切换和进程上下文切换一个最主要的区别是线程的切换虚拟内存空间依然是相同的,但是进程切换是不同的。这两种上下文切换的处理都是通过操作系统内核来完成的。内核的这种切换过程伴随的最显著的性能损耗是将寄存器中的内容切换出

 

另外一个隐藏的损耗是上下文的切换会扰乱处理器的缓存机制。简单的说,一旦去切换上下文,处理器中所有已经缓存的内存地址一瞬间都作废了。还有一个显著的区别是当你改变虚拟内存空间的时候,处理器的页表缓冲(processor’s Translation Lookaside Buffer (TLB))或者相当的神马东西会被全部刷新,这将导致内存的访问在一段时间内相当的低效。但是在线程的切换中,不会出现这个问题。

 

 

 

 

 

posted @ 2017-01-02 10:43  blcblc  阅读(2481)  评论(0编辑  收藏  举报