Linux进程线程初探(概念)

自古美人都是妖i 提交于 2019-11-30 10:43:51

多任务操作系统下通常有3个基本概念:任务、进程、线程。

任务:任务是一个逻辑概念,是为实现某一目的的一些列操作。一次任务可激发多个进程,这些进程相互合作来完成目标。

进程:指一个具有功能的程序在某个数据集合上的一次动态执行过程,它是操作系统进行资源分配和调度的基本单元。

进程和程序的区别:程序是一段静态的代码,是保存在ROM上的指令和数据的集合,没有任何执行的概念;而进程是一个动态的概念,它是程序的一次执行过程,它包括了动态创建、调度、执行和消亡的整个过程。

线程:进程是系统中程序执行和资源分配的基本单位。

每个进程都拥有自己的数据段、代码段、堆栈段,所以进程切换的操作对系统的开销较大。为了提高效率,操作系统引入了线程,也称为轻量级进程。

线程可以对进程的内存空间和资源访问,并与同一进程中的其他线程共享。因此,线程的切换开销比进程小的多。一个进程可以拥有多个线程,其中每个线程共享该进程所拥有的资源和地址空间,因此,任何线程对系统资源的操作都会给其他的线程带来影响,所以应注意多线程中的同步。

那么进程到底拥有那些资源呢,系统又是怎么对进程进行资源分配和调度的呢?

进程的产生:系统首先在新的地址空间里创建进程、读入可执行文件、最后开始执行。系统在一开始就会初始化一个进程,叫做init(),在Linux中进程的创建依赖于函数fork(),fork()通过复制当前进程创建一个子进程,子进程与父进程的区别仅仅在于不同的PID,PPID和某些资源及统计量。所以init进程是所有进程的上辈进程。而exec函数族则负责读取可执行文件并将其载入地址空间开始运行。

进程的终止:进程终止时系统必须保证进程所占用的资源回收,并通知父进程。Linux首先把终止的进程设置为僵尸状态,此时进程已没有运行。它的存在只为父进程提供信息,父进程在某个时间调用wait函数族,回收子进程的退出状态,随后子进程占用的所有资源被释放。

系统是如何管理和调度进程的:Linux内核将率先取得处理器的控制权,再使用调度算法将处理器分配给某个进程。

内核的调度过程:内核将所有进程存放在一个双向链表(进程链表)中,链表的每一项都是一个task_struct结构体。该结构体包含了进程的所有信息,它能完整的描述一个进程,包括进程的状态、进程的基本信息、进程的标识符、内存相关信息、父进程信息、与进程相关的终端信息、当前工作目录、打开的文件信息、所接受的信号等。

其中最为重要的是task_struct中的state(进程状态),主要包括:运行状态(TASK_RUNNING)、可中断的阻塞状态(TASK_INTERRUPTIBLE)、不可中断的阻塞状态(TASK_UNINTERRUPTIBLE)、暂停状态(TASK_STOPPED)、僵尸状态(EXIT_ZOMBLE)、消亡状态(EXIT_DEAD)。它们之间的转换关系如图:

1 进程状态转换关系图

进程所拥有的资源:Linux系统采用虚拟内存管理技术,使得每个进程都有自己独立的地址空间。该地址空间是大小4GB的线性虚拟空间。而这4GB的进程空间又分为两部分 - 用户空间和内核空间。用户空间0-3GB,内核空间3-4GB。用户进程只有使用系统调用的时候才能访问到内核空间。每当进程切换,用户空间就会变化;而内核空间是由内核负责映射,它并不会跟着进程变化,是固定的。每个用户进程的用户空间都是完全独立的、互不相干的。

 

2 进程地址空间分布图

用户空间包括以下几个功能区域:

只读段:包含程序代码(.init .text)和只读数据(.rodata)。

数据段:存放的是全局变量和静态变量。其中可读可写数据段(.data)存放已初始化的全局变量和静态变量,BBS数据段(.bss)存放未初始化的全局变量和静态变量。

栈:有系统自动分配释放,存放函数的参数值、局部变量的值、返回地址等。

堆:存放动态分配的数据,一般有程序动态分配和释放,若程序没有释放,程序结束时由系统回收。

共享库的内存映射区域:这是Linux动态链接器和其他共享库代码映射区域。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!