【Linux】线程的概念以及与进程的区别

目录

背景知识

什么是线程?   

进程和线程的区别 

线程的优缺点


背景知识

        在了解线程前,我们要首先知道,OS是可以做到让进程进行细粒度划分的!

        比如我们所说的进程地址空间中的堆区,它在进程PCB中的mm_structz中有一个start和end来表示整个堆区起始和终止位置,但我们每次malloc在堆上申请一块空间时,会有一个名叫         vm_area struct结构体来表示这块空间,这个结构体里也包含了start和end,但表示的是申请的这块空间的起始和终止位置。然后申请多块空间后,它们之间会使用双链表组织起来。就如下图这样:


        我们要知道,我们平常所运行的exe可执行程序本质上是一个文件,它的内部时遵循如下规则的:

        可执行程序是按照进程地址空间的方式来进行编译的,如上图的右边部分,即编译时,各代码的地址就已经确定。

        可执行程序,内部按照区域被划分成了以4KB大小为单位的块,每个块叫做页帧.

        物理内存内部也被划分成了以4KB为大小的内存块,每个内存块叫做页框,用struct page结构体描述每个内存块的属性。

        在虚拟内存管理中,程序通常使用虚拟内存地址来访问数据,而虚拟地址空间被划分为固定大小的页面(一般是4KB,或称页帧),这些页面在需要时从磁盘上加载到物理内存中,形成连续的物理页框(Page Frame)。当程序在访问某个虚拟内存页面通过页表访问物理内存时,如果该页面当前不在物理内存中,就会触发缺页中断。

       此时操作系统会向物理内存申请一块空间,然后把磁盘中的数据读取到内存中的页框中,然后更新页表,将虚拟内存与物理页框的映射关系进行更新。这样,程序可以继续执行,并且操作系统可以根据需要进行页面置换和内存管理,以保证系统的性能和可用性。

        详细的流程可以下图:


什么是线程?   

        进程:进程是程序的一次运行实例。它是一个独立的、具有独立内存空间的执行环境,包含了程序的代码、数据和执行状态等。每个进程都运行在独立的内存空间中,相互之间不会直接共享内存。              

        线程:线程是进程的一部分,是进程内的一个执行单元。它共享进程的内存空间和资源,包括代码段、数据段和打开的文件等。

        

         Linux下没有真正意义上的线程,因为它是用进程的PCB结构(task_struct)模拟的!

        Linux中CPU视角下的一个PCB可能只是这个进程的一个执行流,而这个 进程可能有多个执行流,即多个线程(多个PCB),所以会更加轻量化。而别的OS是一个进程就享用一份独立的资源,Linux是多个线程共同享用资源。        

        所以,进程和线程统称为轻量级进程.

        虽然说统称为轻量级进程,但是必须得先有一个线程(进程),然后才能有其它的线程,这个线程便称为主线程,这个主线程可以理解为是个进程。

        主线程是进程中的一个特殊线程,通常是在进程创建时由操作系统自动创建的第一个线程。它负责执行程序的入口点,并且负责进行进程的初始化工作。主线程的上下文信息会被记录在该进程对应的 PCB 中。在该进程的 PCB(task_struct)中,除了包含主线程的上下文信息外,还包括了其他线程的上下文信息。

        在我们用户的角度来说,看到的只有进程(主线程),各个进程间包含独立的地址空间,代码数据等。

        但是在内核看来,一个进程内部是具有多个执行流(线程[task_struct])的,它也只认task_struct,所以它是OS运行调度的基本单位,而我们之前写的代码,内部只有一个执行流(task_struct),所以从内核角度上说,这只是进程的一种特殊情况。

        在Linux下,一个进程只有一个执行流  等价于其它OS下的进程

                一个进程有多个执行流  等价于其它OS下的多线程.


综上就是:

        线程是进程的一部分,共享进程资源。但也有自己的一部分数据。

        进程是资源分配的基本单位,线程是OS执行和调度的基本单位。


        这么说起来特别抽象,东西不好解释明白,下面我从网上寻找了一些区别,感觉对于区分线程和进程还是比较助于理解的.

        所以在 Linux 中,进程与线程的区分是基于它们在用户空间的执行环境以及它们共享的资源上。

  1. 执行环境进程是一个独立的执行环境,具有自己的地址空间和其他资源,包括全局变量、文件描述符表等。通过调用系统调用(如fork()exec()),可以创建一个新的进程,该进程使用 task_struct 描述,并有自己的地址空间。

            线程则是在同一个进程内创建的执行流,它与主线程共享相同的地址空间和大部分资源。线程通过调用 clone() 系统调用创建,并共享主线程所拥有的 task_struct 数据结构。每个线程有自己的栈空间和调度信息,但它们共享代码段、全局变量、文件描述符表等。

  2. 资源共享:线程之间共享相同的地址空间和大部分资源,包括全局变量、堆内存、打开的文件等。这也意味着线程之间的通信比进程之间更加高效,因为它们可以直接访问共享内存,无需通过进程间通信机制进行数据的拷贝和传递。


进程和线程的区别 

我总结一下,进程和线程的区别:

  • 进程是资源分配的基本单位,线程是操作系统执行和调度的基本单位.
  • 进程有独立的地址空间,线程没有单独的地址空间(同一进程内的线程共享进程的地址空间)
  • 线程间有更为方便的通信机制,由于线程间共享数据空间,所以一个线程的数据可以直接为其它线程所用。而进程间是独立的空间,需要各种通信方式来共享。

线程的优缺点

优点:

  • 创建:创建一个新线程的代价要比创建一个新进程小得多,因为不需要创建独立的内存空间。
  • 占用资源:线程占用的资源要比进程少很多.
  • 效率:线程在同一进程内共享相同的资源,包括内存空间、全局变量等。这样可以减少资源的重复分配,提高资源利用率
  • 并发性:线程的并发性使得在多个任务之间能够实现同时进行,从而可以提高应用程序的并发能力和性能。

缺点:

  • 缺乏访问控制:进程是访问控制的基本粒度,在一个线程中调用某些OS函数会对整个进程造成影响
  • 性能损失:很少被外部事件阻塞的线程往往无法与共它线程共享同一个处理器。即加了额外的同步和调度开销,而可用的资源不变。
  • 编程难度:编写与调试一个多线程程序比单线程程序困难得多

这里只是大概讲解了下线程的概念以及进程和线程的区别,具体的使用,线程控制等等我们下一章再讲解。

猜你喜欢

转载自blog.csdn.net/weixin_47257473/article/details/132215643