每个进程的系统空间是相同,可有的书上说每个进程
都有一个系统空间堆栈,而且大小固定,只有大概7k
那么大,这是什么原因??
既然系统空间都是一样的,为什么每个进程都要有一个
系统空间堆栈呢,只要一个不就可以了吗?
|
没有公共的系统堆栈,这种实现方式也不太合理,比方说:
系统中有两个进程A,B
某时刻进程B在运行,由于你说的一些原因需要将一些数据存放在所谓的“公共系统堆栈”中
如果这个时候进程开始调度,A进程开始运行,那它该怎么处理这个“公共系统堆栈”内的东西呢?
每个进程的系统堆栈的确是很少,所以那些运行在内核中的进程程序设计需要注意堆栈限制问题
系统空间并不存在这样一个公共堆栈,其实Linux将1G的内核空间分成"物理内存区", "虚拟内存分配区", "高端页面映射区","专用页面映射区", "系统保留映射区"这几个部分,其中物理内存区是最大的,它用来映射系统的物理内存。各部分的划分和大小你可以找相关资料看看
|
首先要搞清楚linux的调度机制,在内核态时是不会发生调度的,而且进入内核态与返回用户态对堆栈的使用是平衡的,那么这样说是不是所有的用户进程都使用一个堆栈呢?
事实并不是这样,linux使用的是独立的,linux中的进程四个基本特性(情景源代码分析)中就包括了进程的内核堆栈
我个人认为这样的设计是为了更好的管理,更强健,虽然理论上只要堆栈的使用平衡,即所有的原子操作后堆栈都是一样的,就可以共享使用,这就相当于只是一种数据结构,但就像上面的兄弟说的一样,linux把堆栈与task_struct放在一起,并用简单操作得到current指针,这在共享堆栈情况下是不允许的
我想还有就是要使进程的独立性,操作系统是很复杂庞大的东西,如果不搞的清晰,独立一些,最后出了问题是很难找的,如果一个进程(中断,调用)的时候由于某种原因(中断处理程序写的不对)使堆栈不平衡了,那就会影响整个系统,而如果堆栈是独立的,那只会影响此进程,大不了把它kill了,内核和别的进程依旧不变,这可能也是linux系统稳定的原因吧(相对windows)
所以像linux的设计:用户与内核分的非常清楚,好理解也更强壮,你死你的,不关别人的事
楼主也可以自己去改成共享堆栈的(不过那可不是小事:)),我想这个问题只是design方式的不同,
当然也有可能别的情况,希望高手指点
|
winux0(阿鱼木木)和yrj说的很对,内核为每个进程分配8k的空间用于保存进程的tss结构,这个空间称为用户进程的内核栈。但用户空间同样拥有用户栈,为什么会有两个堆栈呢???首先要明白这两个栈的作用。
实际上,内核栈对用户程序是不透明的,用户只知道用户栈的存在。调用子函数时,将参数和返回地址压栈,从子函数返回时出栈,这些都是对用户栈进行操作。但用户程序也有访问内核栈的时候,这是通过系统调用达到的,但用户程序根本无需理会内核栈的行为,因为这是操作系统对进程的统一管理和调度。
内核栈的设立有两个目的:1是为了系统对进程进行调度,2是为了在用户进程执行系统调用进入内核空间时有堆栈可用。
|
to winux0:
我的意思是用任务控制块来保存那些寄存器的值,而用一个公用的系统栈
来为每个进程公用(当然用在进程处于系统态时)。
还有,我想问一下,除了为每个用户进程都有一个系统栈外,是不是还有
别的系统栈,因为我感觉每个进程私有的那块系统栈太小了(只有7k左右),
如果发生一些递归调用,7k很可能马上就耗尽了(它不象用户栈那样可以根据需要
动态扩展)。大家知道,每个用户进程的用户栈位于用户空间的顶端,即靠近
3G的地方。那系统空间的顶端是不是也应该有一个系统栈,而这个栈可以动态
扩展?我只是猜想,希望大家讨论一下。。。
楼主看看里面提到了堆栈就是这么小,这也是设计的,还说写中断程序的时候不要用什么递归,大的局部变量:
char buf[1024];
不过对于开发驱动程序的程序员来说应该不会有这样的问题
|
系统堆栈里存了很多重要的东西,比方说一个进程通过系统调用进入内核,它的寄存器等等一些东西需要保存在堆栈中待进程退出内核后恢复
这个可以在楼主看的《linux内核源码情景分析》上册,第301-302页找到描述
此外就像楼上所说,进程进入内核后与用户空间是分开的,这个堆栈就可以用了
|
再查, 发现如果果真如楼主所言, 则系统中定义
的取得当前进程的宏: current就乱了:
因为current是根据(esp & 8191UL)的值得出的, 那你怎么
区分current是哪一个进程? (还根据上面我提供的那个情景,即
一个进程的系统调用被令一个进程中断). 见书p268.
|
就像arnold8792说的那样,Linux代码复杂而庞大,其中一些地方的设计是考虑到了整体的合理性
所以如果没有对整个操作系统各部分结构有比较系统化的理解
而就单单从一个部分去考虑问题的话,往往是不行的