找回密码
 立即注册
Qt开源社区 门户 查看内容

Linux进程与线程(上)

2019-10-11 05:50| 发布者: admin| 查看: 972| 评论: 0

摘要: 1. Linux中的进程与线程(1) 进程与线程的定义进程概念是在上个世纪60年代提出的,进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。进程具有两个基本属 ...

1. Linux中的进程与线程

(1) 进程与线程的定义

进程概念是在上个世纪60年代提出的,进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。进程具有两个基本属性:一是进程是一个可拥有资源的独立单位。二是进程是一个可被处理器独立调度的分配单位。这两个属性构成了程序并发执行的基础。为了使进程并发执行,操作系统还需具备对进程执行一些操作,比如创建进程、撤消进程以及进程的切换。在进行这些操作时,操作系统必须为之付出较多的时间开销。正因如此,在系统中进程不宜设置过多,进程间的切换也不宜频繁,从而限制了并发程度的进一步提高。为解决这一问题,人们想到将进程的两个基本属性分开,即对作为调度和分派的基本单位,不同时作为独立分配资源的单位;对拥有资源的单位,不对之进行频繁的切换。因而线程的思想便产生了。在许多的应用中,一些执行流之间具有内在的逻辑关系,涉及相同的代码或数据。如果将这些执行流放在同一个进程框架下,则这些执行流之间的切换便不涉及地址空间的变化,这也是线程产生的主要动力。引入线程的另一个推动力是线程能较好地支持对称多处理器系统(Symmetric Multiprocessor,SMP)。线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。在面向线程的操作系统中,我们可以把进程看作是线程的容器,系统以进程作为资源分配的独立单位,以线程作为独立运行的单位。前面所定义的进程我们称为传统的进程,或者将其看作是只含有一个线程的进程。知乎作者pansz曾比喻进程线程如下:1、单进程单线程:一个人在一个桌子上吃菜。传统的进程,比如传统的UNIX系统。2、单进程多线程:多个人在同一个桌子上一起吃菜。比如Linux,Windows NT。3*、多进程单线程:一个人可以在不同的桌子上吃菜。一个线程可以从一个进程环境迁移到另一个环境,即允许线程轻松地在不同系统中移动。比如Ra(Clouds)和Enerald系统4*、多进程多线程:结合单进程多线程和多进程单线程的属性。比如TRIX系统。注:3和4是不常见的模型。

(2) 线程和并发

线程也称为轻量级进程,它是一种通过减少开销来提高操作系统性能的软件方法。每个线程只属于一个进程,进程外不能存在任何线程。每个线程代表一个单独的控制流。线程的优点有:
  • 线程的创建和上下文切换更加经济。
  • 提供了进程内的线程的并发性。
  • 高效的通信。
  • 线程允许更大规模和更高效地利用多处理器体系结构。
线程通过以下两种方式实现:
  • 用户级线程:用户管理的线程。
  • 内核级线程:操作系统管理的线程,作用于操作系统内核中。
用户级线程。在这种情况下,内核不知道线程的存在。线程库包含用于创建和销毁线程、在线程之间传递消息和数据、线程调度执行以及保存和恢复线程上下文的代码。应用程序从一个线程开始运行。优点:线程切换不需要内核模式特权。用户级线程可以在任何操作系统上运行。在用户级线程中调度可以是特定的应用程序。用户级线程可以快速创建和管理。缺点:在传统的操作系统中,大多数系统调用都是阻塞的。多线程应用程序不能利用多处理器。内核级线程。在这种情况下,线程管理由内核完成。应用程序中没有线程管理代码。操作系统直接支持内核线程。任何应用程序都可以编程为多线程。一个应用程序中的所有线程都由一个进程支持。内核维护整个进程以及进程中相互独立的线程的上下文信息。内核的调度是在线程的基础上完成的。内核在内核空间中完成线程的创建、调度和管理。内核线程的创建和管理速度通常比用户程慢。优点:内核可以在多进程中同时调度同一进程中的多个线程。如果进程中的一个线程被阻塞,内核可以调度同一进程中的另一个线程。内核例程本身可以是多线程的。缺点:内核线程的创建和管理速度通常比用户线程慢。在同一进程中,将控制从一个线程传输到另一个线程需要切换到内核模式。混合式线程。用户级线程和内核级线程实现方式各有其优缺点,现代操作系统通常都提供上述两种实现方式,这样既利于用户编写并行程序又能够最大限度地发挥多处理器的并行性。因此,如果将两种方法结合起来,则可得到两者的全部优点。内核支持多线程的建立、调度与管理,同时在系统中又提供线程库,允许应用程序建立、调度和管理用户级的线程。

2. Linux线程

(1) 实现原理

线程的概念是上世纪80年代才引入的,所以在Unix系统的早期是没有线程的概念。Unix系统借助于进程机制实现线程,因此在Unix/Linux系统中,进程和线程关系密切,有时也称线程为轻量级进程(light-weight process)。创建线程和进程所使用的底层函数是一样的,都是clone()。从内核看进程和线程是一样的,都有各自不同的PCB,但是线程的PCB和进程的PCB指向内存资源的三级页表都是相同的,因此,进程可以蜕变成线程,每一个线程都有自己的函数调用,拥有自己的用户栈空间,内核区也有一个栈空间用来保存寄存器的值(系统为不同的线程分配CPU时间片,在不同的线程间切换)。

(2) 进程与线程的地址空间

对于进程来说,相同的地址(同一个虚拟地址)在不同的进程中,反复使用而不冲突。原因是他们虽虚拟址一样,但页目录、页表、物理页面各不相同。相同的虚拟址,映射到不同的物理页面内存单元,最终访问不同的物理页面。但是,线程不同!一个进程中的两个线程具有各自独立的PCB,但共享同一个页目录,也就共享同一个页表和物理页面,所以两个PCB共享一个地址空间。实际上,无论是创建进程的fork,还是创建线程的pthread_create,底层实现都是调用同一个内核函数clone。如果复制对方的地址空间,那么就产出一个“进程”;如果共享对方的地址空间,就产生一个“线程”。因此,Linux内核是不区分进程和线程的,只在用户层面上进行区分。所以,线程所有操作函数pthread_*是库函数,而非系统调用。

(3) 资源分配和CPU调度的最小单位

当进程调用pthread_create函数后就蜕变成一个线程,经过多次pthread_create后就有了多个线程,而线程和进程的地位是一样的,当系统在分配时间片时会一视同仁。所以说线程是CPU调度的最小单位,而无论在一个进程中创建多少个线程,它们都共享一个同一个地址空间,所以说进程是资源分配的基本单位。

3. Linux的线程和进程比较

(1) 线程和进程中的全局变量

当一个进程创建一个子进程后,父子进程在各自的地址空间中运行,因此,他们对全局变量的操作互不影响。而线程就不一样了,当一个线程创建一个子线程后,父子线程在同一个地址空间中运行,这就说明父子线程可共享全局变量,对全局变量的操作需要互斥,本节仅演示父子线程可共享变量,有关线程的互斥请看其他资料。下面举例说明。例1: 进程之间不共享全局变量


运行结果如下:


可以看出,父子进程对变量a的操作互不影响。例2: 线程之间共享全局变量


运行结果:



可见,父子线程共享了全局变量a。

(2) 进程与线程控制原语对比


进程

线程

作用
fork()pthread_create()创建
exit()pthread_exit()退出
wait()/waitpid()pthread_join()等待进程/线程退出
Kill()pthread  _cancel()杀死进程、线程
getpid()pthread_self获取当前进程/线程号

(3)多线程与多进程的区别


对比维度

多进程

多线程

总结
数据共享、同步数据共享复杂,需要IPC;数据是分开的,同步简单因为共享进程数据,数据共享简单,因此,同步复杂各有优势
内存、CPU占用内存多,切换复杂、CPU利用率低占用内存少,切换简单,CPU利用率高线程占优
创建销毁、切换创建销毁、切换复杂,速度慢创建销毁、切换简单,速度快线程占优
编程、调试编程简单、调试简单编程复杂、调试复杂进程占优
可靠性进程间不会影响一个线程挂掉将会导致整个进程挂掉进程占优
分布式适用于多核、多机分布式;扩展机器简单适用于多核分布式进程占优

----------------------------------------------------------------------------------------------------------------------
我们尊重原创,也注重分享,文章来源于微信公众号:操作系统学习,建议关注公众号查看原文。如若侵权请联系qter@qter.org。
----------------------------------------------------------------------------------------------------------------------

鲜花

握手

雷人

路过

鸡蛋

公告
可以关注我们的微信公众号yafeilinux_friends获取最新动态,或者加入QQ会员群进行交流:190741849、186601429(已满) 我知道了