Xin*_*nus 239 multithreading operating-system process
最近,我在面试中被问到一个问题,即流程和线程之间的区别.真的,我不知道答案.我想了一会儿,给了一个非常奇怪的答案.
线程共享相同的内存,而进程则没有.在回答这个问题之后,面试官给了我一个邪恶的微笑,并向我解释了以下问题:
问:你知道程序划分的部分吗?
我的回答:是的(认为这是一个简单的)堆栈,数据,代码,堆
问:那么,告诉我:线程共享哪些段?
我无法回答这个问题并最终说出了所有这些.
请问,任何人都可以为流程和线程之间的差异提供正确和令人印象深刻的答案吗?
Gre*_*ill 159
你是非常正确的,但线程共享除堆栈之外的所有段.线程有独立的调用堆栈,但是其他线程堆栈中的内存仍然可以访问,理论上你可以在一些其他线程的本地堆栈帧中保存一个指向内存的指针(尽管你可能应该找到一个放置内存的更好位置!).
Rob*_*nes 44
真正需要指出的是,这个问题确实存在两个方面 - 理论方面和实施方面.
首先,让我们看一下理论方面.您需要了解流程在概念上是什么来理解流程和线程之间的区别以及它们之间共享的内容.
我们从第2.2.2节Tanenbaum的现代操作系统3e中的经典线程模型中得到以下结论:
流程模型基于两个独立的概念:资源分组和执行.有时将它们分开是有用的; 这是线程进来的地方....
他继续:
查看流程的一种方法是将相关资源组合在一起.进程具有包含程序文本和数据以及其他资源的地址空间.这些资源可能包括打开文件,子进程,待处理警报,信号处理程序,记帐信息等.通过以流程的形式将它们组合在一起,可以更容易地管理它们.进程的另一个概念是执行线程,通常缩写为只是线程.该线程有一个程序计数器,用于跟踪下一个要执行的指令.它有寄存器,它保存当前的工作变量.它有一个堆栈,其中包含执行历史记录,每个过程调用一个帧但尚未返回.虽然线程必须在某些进程中执行,线程及其过程是不同的概念,可以单独处理.流程用于将资源组合在一起; 线程是计划在CPU上执行的实体.
再向下,他提供了下表:
Per process items | Per thread items
------------------------------|-----------------
Address space | Program counter
Global variables | Registers
Open files | Stack
Child processes | State
Pending alarms |
Signals and signal handlers |
Accounting information |
Run Code Online (Sandbox Code Playgroud)
以上是线程工作所需的内容.正如其他人所指出的那样,诸如段之类的东西是依赖于OS的实现细节
Ale*_*ski 27
告诉采访者,这完全取决于操作系统的实施.
以Windows x86为例.只有2个段[1],代码和数据.它们都映射到整个2GB(线性,用户)地址空间.Base = 0,Limit = 2GB.他们会做一个,但x86不允许段读/写和执行.所以他们做了两个,并设置CS指向代码描述符,其余(DS,ES,SS等)指向另一个[2].但两者都指向相同的东西!
面试你的人做了一个隐藏的假设,他/她没有陈述,这是一个愚蠢的伎俩.
所以关于
问:那么告诉我哪个段线程共享?
这些细分与问题无关,至少在Windows上是这样.线程共享整个地址空间.只有1个堆栈段,SS,它指向与DS,ES和CS完全相同的东西[2].即整个血腥的用户空间.0-2GB.当然,这并不意味着线程只有1个堆栈.当然,每个都有自己的堆栈,但x86段不用于此目的.
也许*nix做了不同的事情.谁知道.这个问题基于的前提被打破了.
ntsd notepad:cs=001b ss=0023 ds=0023 es=0023小智 19
通常,线程称为轻量级过程.如果我们将内存分为三个部分,那么它将是:代码,数据和堆栈.每个进程都有自己的代码,数据和堆栈部分,由于这个上下文,切换时间有点高.为了减少上下文切换时间,人们提出了线程的概念,它与其他线程/进程共享数据和代码段,并且它有自己的STACK段.
小智 17
进程具有代码,数据,堆和堆栈段.现在,线程OR线程的指令指针(IP)指向进程的代码段.所有线程共享数据和堆段.那么堆栈区呢?什么是堆栈区域?它是一个由进程创建的区域,仅供其线程使用...因为堆栈可以比堆等更快的方式使用.进程的堆栈区域在线程之间划分,即如果有3个线程,则该过程的堆栈区域分为3个部分,每个部分分配给3个线程.换句话说,当我们说每个线程都有自己的堆栈时,该堆栈实际上是分配给每个线程的进程堆栈区域的一部分.当一个线程完成其执行时,该进程将回收该线程的堆栈.实际上,不仅进程的堆栈在线程之间划分,而且线程使用的所有寄存器集合如SP,PC和状态寄存器都是进程的寄存器.因此,在共享时,代码,数据和堆区域是共享的,而堆栈区域只是在线程之间划分.
Kev*_*son 12
线程共享代码和数据段以及堆,但它们不共享堆栈.
\n\n\n除了全局内存之外,线程还共享许多其他属性(即,这些属性对于进程来说是全局的,而不是特定于线程的)。这些属性包括以下内容:
\n\n\n
\n\n- 进程ID和父进程ID;
\n- 进程组ID和会话ID;
\n- 控制终端;
\n- 进程凭证(用户和组 ID);
\n- 打开文件描述符;
\n- 记录使用创建的锁
\nfcntl();- 信号处置;
\n- 文件系统\xe2\x80\x93相关信息:umask、当前工作目录、根目录;
\n- 间隔定时器 (
\nsetitimer()) 和 POSIX 定时器 (timer_create());- System V 信号量 undo (
\nsemadj) 值(第 47.8 节);- 资源限制;
\n- 消耗的 CPU 时间(由 返回
\ntimes());- 消耗的资源(由 返回
\ngetrusage());和- \n
setpriority()不错的值(由和设置nice())。每个线程的独特属性如下:
\n\n\n
\n- 线程 ID(第 29.5 节);
\n- 信号掩码;
\n- 线程特定数据(第 31.3 节);
\n- 交替信号堆栈 (
\nsigaltstack());- 错误号变量;
\n- 浮点环境(参见
\nfenv(3));- 实时调度策略和优先级(第 35.2 和 35.3 节);
\n- CPU 亲和性(特定于 Linux,在第 35.4 节中描述);
\n- 功能(Linux 特定的,在第 39 章中描述);和
\n- 堆栈(局部变量和函数调用链接信息)。
\n
摘自:《Linux 编程接口:Linux 和 UNIX 系统编程手册》,Michael Kerrisk,第 619 页
\n