Linux进程和线程的比较

进程与线程

参考:http://www.cnblogs.com/blueclue/archive/2010/07/16/1778855.html

首先比较Linux进程和线程的创建的区别,以此展开:

创建进程:(1)调用fork(),为子进程新建内核栈、pthread_info和task_struct,复制父进程的大部分的参数,采用写时复制(copy-on-write)辅助父进程的资源,修改子进程如pid、ppid等重要资源。(2)调用exec()为子进程分配地址空间,载入执行程序。

创建线程:与进程创建没有大的区别,唯一不同的就是,在调用clone()的fork()参数表里指明共享的资源。

标志                    含义

CLONE_PARENT   创建的子进程的父进程是调用者的父进程,新进程与创建它的进程成了“兄弟”而不是“父子”

CLONE_FS           子进程与父进程共享相同的文件系统,包括root、当前目录、umask

CLONE_FILES      子进程与父进程共享相同的文件描述符(file descriptor)表

CLONE_NEWNS   在新的namespace启动子进程,namespace描述了进程的文件hierarchy

CLONE_SIGHAND   子进程与父进程共享相同的信号处理(signal handler)表

CLONE_PTRACE   若父进程被trace,子进程也被trace

CLONE_VFORK     父进程被挂起,直至子进程释放虚拟内存资源

CLONE_VM           子进程与父进程运行于相同的内存空间

CLONE_PID          子进程在创建时PID与父进程一致

CLONE_THREAD    Linux 2.4中增加以支持POSIX线程标准,子进程与父进程共享相同的线程群

为什么对于大多数合作性任务,多线程比多个独立的进程更优越呢?这是因为,线程共享相同的内存空间。不同的线程可以存取内存中的同一个变量。所以,程序中的所有线程都可以读或写声明过的全局变量。如果曾用fork() 编写过重要代码,就会认识到这个工具的重要性。为什么呢?虽然fork() 允许创建多个进程,但它还会带来以下通信问题:如何让多个进程相互通信,这里每个进程都有各自独立的内存空间。对这个问题没有一个简单的答案。虽然有许多不同种类的本地IPC (进程间通信),但它们都遇到两个重要障碍:

  • 强加了某种形式的额外内核开销,从而降低性能。
  • 对于大多数情形,IPC不是对于代码的“自然”扩展。通常极大地增加了程序的复杂性。

双重坏事: 开销和复杂性都非好事。如果曾经为了支持 IPC而对程序大动干戈过,那么您就会真正欣赏线程提供的简单共享内存机制。由于所有的线程都驻留在同一内存空间,POSIX线程无需进行开销大而复杂的长距离调用。只要利用简单的同步机制,程序中所有的线程都可以读取和修改已有的数据结构。而无需将数据经由文件描述符转储或挤入紧窄的共享内存空间。仅此一个原因,就足以让您考虑应该采用单进程/多线程模式而非多进程/单线程模式。

为什么要用线程?

与标准 fork()相比,线程带来的开销很小。内核无需单独复制进程的内存空间或文件描述符等等。这就节省了大量的CPU时间,使得线程创建比新进程创建快上十到一百倍。因为这一点,可以大量使用线程而无需太过于担心带来的CPU 或内存不足。使用 fork() 时导致的大量 CPU占用也不复存在。这表示只要在程序中有意义,通常就可以创建线程。

当然,和进程一样,线程将利用多CPU。如果软件是针对多处理器系统设计的,这就真的是一大特性(如果软件是开放源码,则最终可能在不少平台上运行)。特定类型线程程序(尤其是CPU密集型程序)的性能将随系统中处理器的数目几乎线性地提高。如果正在编写CPU非常密集型的程序,则绝对想设法在代码中使用多线程。一旦掌握了线程编码,无需使用繁琐的IPC和其它复杂的通信机制,就能够以全新和创造性的方法解决编码难题。所有这些特性配合在一起使得多线程编程更有趣、快速和灵活。

什么是线程?

  • 专业点的说法,线程被定义为一个独立的指令流,它本身的运转由操作系统来安排,但是,这意味着什么呢?
  • 对软件开发者来说,解释线程最好的描述就是“procedure”可以独立于主程序运行。
  • 再进一步,设想一个包含了大量procedure的主程序,然后想象所有这些procedure在操作系统的安排下一起或者独立的运行,这就是对于多线程程序的一个简单描述。
  • 问题是,它是如何实现的呢?
  • 在弄懂线程之前,第一步要搞清楚Unix进程。进程被操作系统创建,并需要相当多的“开支”,进程包含如下程序资源和程序执行状态信息:
  1. 进程ID,进程群组ID,用户ID,群组ID
  2. 环境
  3. 工作目录
  4. 程序指令
  5. 寄存器
  6. 文件描述符
  7. 信号动作
  8. 共享库
  9. 进程间通信工具(例如消息队列,管道,信号量,共享内存)

Unix进程                                                            Unix进程内部的线程

  • 线程使用和在进程内的生存,仍由操作系统来安排并且独立的实体来运行,很大程度上是因为它们为可执行代码的存在复制了刚刚好的基本资源。
  • 这个独立的控制流之所以可以实现,是因为线程维护着如下的东西:
  1. 栈指针
  2. 寄存器
  3. 调度属性(例如规则和优先级)
  4. 等待序列和阻塞信号
  5. 线程拥有的数据
  • 所以,总的来说,Unix环境里的线程有如下特点:
  1. 它生存在进程中,并使用进程资源;
  2. 拥有它自己独立的控制流,前提是只要它的父进程还存在,并且OS支持它;
  3. 它仅仅复制可以使它自己调度的必要的资源;
  4. 它可能会同其它与之同等独立的线程分享进程资源;
  5. 如果父进程死掉那么它也会死掉——或者类似的事情;
  6. 它是轻量级的,因为大部分的开支已经在它的进程创建时完成了。
  • 因为在同一进程内的线程分享资源,所以:
  1. 一个线程对共享的系统资源做出的改变(例如关闭一个文件)会被所有的其它线程看到;
  2. 指向同一地址的两个指针的数据是相同的;
  3. 对同一块内存进行读写操作是可行的,但需要程序员作明确的同步处理操作。
时间: 2024-11-04 00:30:02

Linux进程和线程的比较的相关文章

Linux进程或线程绑定到CPU

Linux进程或线程绑定到CPU 为了让程序拥有更好的性能,有时候需要将进程或线程绑定到特定的CPU,这样可以减少调度的开销和保护关键进程或线程. 进程绑定到CPU Linux提供一个接口,可以将进程绑定到特定的CPU: #include <sched.h> int sched_setaffinity(pid_t pid, size_t cpusetsize, const cpu_set_t *mask); int sched_getaffinity(pid_t pid, size_t cpu

Linux 进程、线程运行在指定CPU核上

/******************************************************************************** * Linux 进程.线程运行在指定CPU核上 * 说明: * affinity参数决定了进程.线程是否可在CPU多核之间切换,当然,并不是说就不进行 * 线程切换. * * 2017-9-22 深圳 龙华樟坑村 曾剑锋 *********************************************************

linux 进程 VS 线程

在进行编程模型选择时,总是要对进程和线程的优缺点进行对比,才能做出决定.这里对常用的对比纬度进行了总结,如有新发现,我会更新. linux 进程 VS 线程

探究Linux进程及线程堆栈专题&lt;一&gt;

“你定义了那么多全局变量,系统才给你分配了几百KB,这样做是不是太耗内存了?”,一同学问道. 老早就听说嵌入式系统各种资源有限啊,不能分配大空间啊要注意节约资源之类的(...貌似米神4的配置要完爆我的thinkpad了...).那是不是全局变量的使用真的会占用很大系统内存,而系统真的才分配几百KB空间给我呢? 我不信,所以我要尝试一下: 全局变量,肯定是要占用内存的,但无论是不是全局变量,只要是已定义的变量都会占用内存,这个和是否是全局的没啥关系,只是占用的区域不一样而已(详见APUE存储器安排

linux进程、线程(or子进程)、资源占用查看

#  linux进程.线程(or子进程).资源占用查看 查看进程: ps -ef | more  (-e:所有进程,-f:全格式) ++++++++++++++++++++++++++++++++++++ + UID :用户ID                     + + PID :进程ID                           + + PPID :父进程ID                                                 + + C :CPU占

windows和linux进程与线程的理解

对于windows来说,进程和线程的概念都是有着明确定义的,进程的概念对应于一个程序的运行实例(instance),而线程则是程序代码执行的最小单元.也就是说windows对于进程和线程的定义是与经典OS课程中所教授的进程.线程概念相一致的. 提供API,CreateThread()用于建立一个新的线程,传递线程函数的入口地址和调用参数给新建的线程,然后新线程就开始执行了. windows下,一个典型的线程拥有自己的堆栈.寄存器(包括程序计数器PC,用于指向下一条应该执行的指令在内存中的位置),

Linux进程与线程的区别

cnyinlinux 本文较长,耐心阅读,必有收获! 进程与线程的区别,早已经成为了经典问题.自线程概念诞生起,关于这个问题的讨论就没有停止过.无论是初级程序员,还是资深专家,都应该考虑过这个问题,只是层次角度不同罢了.一般程序员而言,搞清楚二者的概念,在工作实际中去运用成为了焦点.而资深工程师则在考虑系统层面如何实现两种技术及其各自的性能和实现代价.以至于到今天,Linux内核还在持续更新完善(关于进程和线程的实现模块也是内核完善的任务之一). 本文将以一个从事Linux平台系统开发的程序员角

操作系统:Linux进程与线程

这里是一部分内容,还会做修改. 一:目的及内容 学习fork(),exec,pthread库函数的使用,阅读源码,分析fork,exec,pthread_create函数的机理 代码实现: 进程A创建子进程B 子进程B与父进程A分别对应不同的可执行体:A打印Hello world,B实现sum累加 进程B具有三线程,主线程创建新的线程1实现sum累加(从1到参数x),线程2监控输入参数x 若输入x是非负整数,线程1开始计算:如果线程1正在计算前次程序,线程2的输入非负整数和最近一次的又不同,线程

【Linux】第二章 Linux进程与线程(下)

4. Linux内核级线程与用户级线程 POSIX线程调度是一个混合模型,既支持用户级也支持内核级的线程.在创建线程时对contentionscope属性可设置为: PTHREAD_SCOPE_PROCESS.它表示新创建的线程与它所在的进程中的其他线程竞争处理器资源,等同用户级线程. PTHREAD_SCOPE_SYSTEM.说明新创建的线程就像内核级线程一样在全系统的范围内竞争处理器资源. (1) 内核级线程 线程的创建.撤销和切换等,都需要内核直接实现,即内核了解每一个作为可调度实体的线程