smw*_*dia 51 c++ multithreading operating-system process
是的,我读过许多与操作系统相关的资料.我还在读书.但似乎所有这些都是以"抽象"的方式描述过程和线程,这使得他们的行为和逻辑组织得到了很多高层次的阐述.我想知道他们身体上是什么?在我看来,它们只是一些内存中的"数据结构",它们由内核代码维护和使用,以便于程序的执行.例如,操作系统使用一些过程数据结构(PCB)来描述为某个程序分配的过程的各个方面,例如其优先级,地址空间等.这样可以吗?
Dmi*_*try 29
要了解进程和线程之间的区别,首先需要知道的是,进程不会运行,线程会运行.
那么,什么是线程?最近我可以解释它是一个执行状态,如:CPU寄存器,堆栈,批次的组合.您可以通过在任何给定时刻打破调试器来查看该证明.你看到了什么?一个调用堆栈,一组寄存器.这就是它.那是线程.
那么,现在,什么是流程.好吧,它就像一个用于运行线程的抽象"容器"实体.就第一个近似的操作系统而言,它是一个实体操作系统分配一些VM,分配一些系统资源(如文件句柄,网络套接字),&c.
他们如何一起工作?操作系统通过为其保留一些资源并启动"主"线程来创建"进程".然后该线程可以产生更多线程.这些是一个过程中的线程.他们或多或少可以以某种方式分享这些资源(比如说,锁定可能需要他们不要破坏他人的乐趣和c).从那时起,OS通常负责维护那些线程"内部"VM(检测并阻止尝试访问不属于该进程的内存),提供某种类型的线程调度,以便它们可以运行"一后另一个和 - 不只是一,所有的时间".
Aar*_*nLS 28
通常,当您运行像notepad.exe这样的可执行文件时,这会创建一个进程.这些进程可能会产生其他进程,但在大多数情况下,您运行的每个可执行文件都有一个进程.在这个过程中,可以有很多线程.通常起初有一个线程,通常从程序"入口点"开始,这通常是main函数.指令按顺序逐个执行,就像只有一只手的人一样,一个线程在移动到下一个之前一次只能做一件事.
第一个线程可以创建其他线程.每个附加线程都有自己的入口点,通常用函数定义.该过程就像是在其中生成的所有线程的容器.
这是一个非常简单的解释.我可以详细介绍,但可能与您在教科书中找到的内容重叠.
编辑:你会注意到我的解释中有很多"通常"的东西,因为偶尔有一些罕见的程序可以做出截然不同的事情.
Jör*_*tag 10
以非抽象方式描述线程和进程几乎是不可能的原因之一是它们是抽象的.
他们的具体实施差别很大.
比较一个Erlang进程和一个Windows进程:Erlang进程非常轻量级,通常少于400字节.您可以在不太新的笔记本电脑上启动1000万个进程而不会出现任何问题.他们启动非常快,他们死非常迅速,我们希望你能够使用它们很短的任务.每个Erlang进程都有自己的垃圾收集器.Erlang进程永远不会共享内存.
Windows进程非常繁重,有时甚至数百个MiBytes.如果你幸运的话,你可以在一台强大的服务器上启动它们中的几千个.他们开始慢慢死去.Windows进程是应用程序的单元,例如IDE或文本编辑器或字处理器,因此通常需要它们存在相当长的时间(至少几分钟).他们有自己的地址空间,但没有垃圾收集器.Windows进程可以共享内存,但默认情况下它们不共享内存.
线程是一个类似的问题:x86上的NPTL Linux线程可以小到4 KiByte,并且有一些技巧,你可以在32位x86机器上启动800000+.该机器肯定可以使用数千甚至数万个线程..NET CLR线程的最小大小约为1 MiByte,这意味着其中只有4000个会占用32位计算机上的整个地址空间.因此,虽然4000 NPTL Linux线程通常不是问题,但您甚至无法启动 4000 .NET CLR线程,因为在此之前您将耗尽内存.
OS进程和OS线程在不同的操作系统之间也实现了非常不同的实现.主要的两种方法是:内核只知道进程.线程由用户空间库实现,完全不了解内核.在这种情况下,还有两种方法:1:1(每个线程映射到一个内核进程)或m:n(m个线程映射到n个进程,通常m> n,通常n == #CPU).这是线程发明后许多操作系统采用的早期方法.但是,它通常被认为是低效的,并且已经通过第二种方法在几乎所有系统上被替换:线程在内核中实现(至少部分地),因此内核现在知道两个不同的实体,即线程和进程.
第三条路线的一个操作系统是Linux.在Linux中,线程既不在用户空间也不在内核中实现.相反,内核提供了一个抽象两种线程和进程(实际上一对夫妇的更多的东西),称为任务.任务是一个内核预定实体,它带有一组标志,用于确定它与其兄弟姐妹共享哪些资源以及哪些资源是私有的.
根据您设置这些标志的方式,您可以获得一个Thread(几乎可以共享所有内容)或一个Process(共享所有系统资源,如系统时钟,文件系统命名空间,网络命名空间,用户ID命名空间,进程ID命名空间,但不要共享地址空间).但你也可以得到其他一些非常有趣的东西.您可以轻松获取BSD样式的jail(基本上与Process相同的标志,但不共享文件系统或网络命名空间).或者您可以获得其他操作系统称为虚拟化容器或区域(如jail,但不共享UID和PID命名空间和系统时钟).几年前,通过一种名为KVM(内核虚拟机)的技术,您甚至可以获得一个完整的虚拟机(不共享任何内容,甚至不包括处理器的页面表).[关于这一点的很酷的事情是你可以在内核中重用高度调整的成熟任务调度程序来完成所有这些事情.Xen虚拟机经常批评的一件事是其调度程序的性能不佳.KVM开发人员拥有比Xen更好的调度程序,最好的是他们甚至不必为它编写一行代码!]
因此,在Linux上,线程和进程的性能比Windows和许多其他系统更接近,因为在Linux上,它们实际上是相同的.这意味着使用模式非常不同:在Windows上,您通常根据其权重决定使用线程和进程:我可以负担进程还是应该使用线程,即使我实际上不想共享州?在Linux(通常是Unix)上,您可以根据它们的语义来决定:我是否真的想要共享状态?
其中一个原因为什么过程往往是在Unix上比在Windows更轻,是不同的使用:在Unix上,过程都是并发性和功能的基本单位.如果要使用并发,则使用多个进程.如果您的应用程序可以分解为多个独立的部分,则使用多个进程.每个过程只完成一件事,只做一件事.即使是简单的单行shell脚本也经常涉及数十个或数百个进程.应用程序通常由许多(通常是短暂的)进程组成.
在Windows上,线程是并发的基本单位,COM组件或.NET对象是功能的基本单位.应用程序通常由一个长时间运行的进程组成.
同样,它们用于非常不同的目的,并且具有非常不同的设计目标.这不是一个或另一个更好或更坏,只是它们是如此不同,以至于共同特征只能被非常抽象地描述.
几乎所有关于线程和进程的事情都是: