进程基本概念理解

简介:

一、进程和程序

1.进程的基本概念

  所谓进程是由正文段用户数据段以及系统数据段共同组成的一个执行环境,是一个动态实体。

2.程序的基本概念

  程序只是一个普通文件,是一个机器代码指令和数据的集合,这些指令和数据存储在磁盘上的一个可执行映像中,所以,程序是一个静态的实体。

wKiom1na8_WAsle4AAAnwz3_ZWo119.png

3.进程的组成部分

(1)正文段:存放被执行的机器指令。这个段是只读的(所以,在这里不能写自己能修改的代码),它允许系统中正在运行的两个或多个进程之间能够共享这一代码。

(2)用户数据段:存放进程在执行时直接进行操作的所有数据,包括进程使用的全部变量在内。显然,这里包含的信息可以被改变。虽然进程之间可以共享正文段,但是每个进程需要有它自己的专用用户数据段。

(3)系统数据段:该段有效地存放程序运行的环境。事实上,这正是程序和进程的区别所在。作为动态事物,进程是正文段、用户数据段和系统数据段的信息的交叉综合体,其中系统数据段是进程实体最重要的一部分,之所以说它有效地存放程序运行的环境,是因为这一部分存放有进程的控制信息。Linux为每个进程建立了task_struct数据结构来容纳这些控制信息。

4.进程和程序总结

  程序装入内存后就可以运行了:在指令指针寄存器的控制下,不断地将指令取至CPU运行。这些指令控制的对象不外乎各种存储器(内存、外存和各种CPU寄存器等),这些存储器中保存有待运行的指令和待处理的数据,当然,指令只有到CPU才能发挥其作用。

  Linux是一个多任务操作系统,也就是说,可以有多个程序同时装入内存并运行,操作系统为每个程序建立一个运行环境即创建进程,每个进程拥有自己的虚拟地址空间,它们之间互不干扰,即使要相互作用(例如多个进程合作完成某个工作),也要通过内核提供的进程间通信机制(IPC)

二、task_struct结构描述

1.Linux中的每个进程由一个task_struct数据结构来描述,task_struct其实就是通常所说的“进程控制块”即PCB。task_struct容纳了一个进程的所有信息,是系统对进程进行控制的唯一手段,也是最有效的手段。

2.task_struct数据结构所有域如下:

*进程状态(State);

wKioL1nbES7DwaJOAABabyaaZfc304.png

  僵死状态:进程虽然已经终止,但由于某种原因,父进程还没有执行wait()系统调用,终止进程的
信息也还没有回收。

*进程调度信息(Scheduling Information);


wKiom1nbEvPhmHuKAAA9hO7T7DI798.png

wKiom1nbEvPQVkBZAABE300oFQM152.png

调度策略

只有root用户能通过sched_setscheduler()系统调用来改变调度策略。

*各种标识符(Identifiers);

wKioL1nbE2XBBQ1oAABRJjD_MnU439.png

*进程通信有关信息(IPC,Inter_Process Communication);

  Linux 支持多种不同形式的通信机制。它支持典型的UNIX通信机制(IPC Mechanisms):信号、管道,也支持System V通信机制:共享内存、信号量和消息队列。

wKioL1nbFT_CiW2lAABw2l4C30A197.png

*时间和定时器信息(Times and Timers);

  一个进程从创建到终止叫做该进程的生存期(lifetime)。进程在其生存期内使用 CPU的时间,内核都要进行记录,以便进行统计、计费等有关操作。进程耗费CPU的时间由两部分组成:一是在用户模式(或称为用户态)下耗费的时间、一是在系统模式(或称为系统态)下耗费的时间。每个时钟滴答,也就是每个时钟中断,内核都要更新当前进程耗费CPU的时间信息。

wKiom1nbF6LhiPRBAABhIvQu0sY077.png

 建立了“时间”的概念,“定时”就是轻而易举的了,无非是判断系统时间是否到达某个时刻,然后执行相关的操作而已。Linux提供了许多种定时方式,用户可以灵活使用这些方式来为自己的程序定时。

wKioL1nbF2aidamQAACdN24aPus521.png

*进程链接信息(Links);

  程序创建的进程具有父/子关系。因为一个进程能创建几个子进程,而子进程之间有兄弟关系,在 task_struct结构中有几个域来表示这种关系。

  在Linux系统中,除了初始化进程init,其他进程都有一个父进程或称为双亲进程。 可以通过 fork()或 clone()系统调用来创建子进程, 除了进程标识符(PID)等要的信息外,子进程的task_struct结构中的绝大部分的信息都是从父进程中拷贝,或说“克隆”过来的。系统有必要记录这种“亲属”关系,使进程之间的协作更加方便,例如父进程给子进程发送杀死(kill)信号、父子进程通信等,就可以用这种关系很方便地实现。

wKioL1nbFQChCoaeAACSUEmFqeo609.png

*文件系统信息(File System);

  进程可以打开或关闭文件,文件属于系统资源,Linux内核要对进程使用文件的情况进行记录。task_struct结构中有两个数据结构用于描述进程与文件相关的信息。其中,fs_struct中描述了两个 VFS索引节点,这两个索引节点叫做root和pwd,分别指向进程的可执行映像所对应的根目录和当前目录或工作目录。file_struct结构用来记录了进程打开的文件的描述符。

  在文件系统中,每个VFS索引节点唯一描述一个文件或目录,同时该节点也是向更低层的文件系统提供的统一的接口。 

wKioL1nbGlmwUThNAAA0Rqw-1Mw994.png

*虚拟内存信息(Virtual Memory);
*页面管理信息(page);
*对称多处理器(SMP)信息;
*和处理器相关的环境(上下文)信息(Processor Specific Context);

*其他信息。

三、task_struct 结构在内存中的存放

内核栈:每个进程都有自己的内核栈。当进程从用户态进入内核态时,CPU就自动地设置该进程的内核栈。

wKiom1nbH8_CJaedAAAroLYyKeQ094.png

 从这个结构可以看出,内核栈占8KB 的内存区。实际上,进程的task_struct结构所占的内存是由内核动态分配的,更确切地说,内核根本不给task_struct分配内存,而仅仅给内核栈分配8KB的内存,并把其中的一部分给task_struct使用。

  task_struct结构大约占1K字节左右,其具体数字与内核版本有关,因为不同的版本其域稍有不同。因此,内核栈的大小不能超过7KB,否则,内核栈会覆盖task_struct结构,从而导致内核崩溃。不过,7KB大小对内核栈已足够。

  把task_struct结构与内核栈放在一起具有以下好处:
*内核可以方便而快速地找到这个结构,用伪代码描述如下:
  task_struct = (struct task_struct *) STACK_POINTER & 0xffffe000(8K)
*避免在创建进程时动态分配额外的内存。
*task_struct 结构的起始地址总是开始于页大小(PAGE_SIZE)的边界。

四、进程的组织方式

1.哈希表

 哈希表是进行快速查找的一种有效的组织方式。Linux在进程中引入的哈希表叫做pidhash,在include/linux/sched.h 中定义。

2.双向循环链表

  哈希表的主要作用是根据进程的pid可以快速地找到对应的进程,但它没有反映进程创建的顺序,也无法反映进程之间的亲属关系,因此引入双向循环链表。每个进程task_struct结构中的prev_task和next_task域用来实现这种链表。

3.运行队列

  当内核要寻找一个新的进程在CPU上运行时,必须只考虑处于可运行状态的进程(即在TASK_RUNNING 状态的进程) ,因为扫描整个进程链表是相当低效的,所以引入了可运行状态进程的双向循环链表,也叫运行队列(runqueue)。

4.进程的运行队列链表

 该队列通过task_struct结构中的两个指针run_list链表来维持。队列的标志有两个:一个是“空进程”idle_task,一个是队列的长度。

  空进程是个比较特殊的进程,只有系统中没有进程可运行时它才会被执行,Linux将它看作运行队列的头,当调度程序遍历运行队列,是从idle_task开始、至idle_task结束的,在调度程序运行过程中,允许队列中加入新出现的可运行进程,新出现的可运行进程插入到队尾,这样的好处是不会影响到调度程序所要遍历的队列成员,可见,idle_task是运行队列很重要的标志。另一个重要标志是队列长度,也就是系统中处于可运行状态(TASK_RUNNING)的进程数目,用全局整型变量nr_running表示,在/kernel/fork.c 中定义。

5.等待队列

  顾名思义,就是等待执行的进程所组成的队列。等待队列在内核中有很多用途,尤其对中断处理、进程同步及定时用处更大。

五、内核线程

  内核线程或叫守护进程,在操作系统中占据相当大的比例,你可以用“ps”命令查看系统中的进程,这时会发现很多以“d”结尾的进程名,这些进程就是内核线程。内核线程是由kernel_thread ( )函数在内核态下创建。

  内核线程也可以叫内核任务,它们周期性地执行,例如,磁盘高速缓存的刷新,网络连接的维护,页面的换入换出等。在Linux中,内核线程与普通进程有一些本质的区别,从以下几个方面可以看出二者之间的差异。
*内核线程执行的是内核中的函数,而普通进程只有通过系统调用才能执行内核中的函数。
*内核线程只运行在内核态,而普通进程既可以运行在用户态,也可以运行在内核态。
*因为内核线程指只运行在内核态,因此,它只能使用大于PAGE_OFFSET(3G)的地址空间。另一方面,不管在用户态还是内核态,普通进程可以使用4GB的地址空间。

  由于kernel_thread包含大部分汇编代码,大致和下面代码等价:

1
2
3
4
5
6
7
8
9
10
11
int  kernel_thread( int (*fn)( void  *), void  * arg,unsigned  long  flags)
{
     pid_t p ;
     p = clone(0, flags | CLONE_VM);
     if (p)  /* parent */
     return  p;
     else /* child */
     fn(arg) ;
     exit ( ) ;
     }
}

六、进程的权能

  Linux 用“权能(capability)”表示一进程所具有的权力。一种权能仅仅是一个标志,它表明是否允许进程执行一个特定的操作或一组特定的操作。这个模型不同于传统的“超级用户对普通户”模型,在后一种模型中,一个进程要么能做任何事情,要么什么也不能做,这取决于它的有效 UID。

  任何时候,每个进程只需要有限种权能,这是其主要优势。因此,即使一位有恶意的用户使用有潜在错误程序,他也只能非法地执行有限个操作类型。




本文转自 8yi少女的夢 51CTO博客,原文链接:http://blog.51cto.com/zhaoxiaohu/1970945,如需转载请自行联系原作者

相关文章
|
7月前
|
存储 Linux API
【Linux进程概念】—— 操作系统中的“生命体”,计算机里的“多线程”
在计算机系统的底层架构中,操作系统肩负着资源管理与任务调度的重任。当我们启动各类应用程序时,其背后复杂的运作机制便悄然展开。程序,作为静态的指令集合,如何在系统中实现动态执行?本文带你一探究竟!
【Linux进程概念】—— 操作系统中的“生命体”,计算机里的“多线程”
|
4月前
|
Unix Linux
对于Linux的进程概念以及进程状态的理解和解析
现在,我们已经了解了Linux进程的基础知识和进程状态的理解了。这就像我们理解了城市中行人的行走和行为模式!希望这个形象的例子能帮助我们更好地理解这个重要的概念,并在实际应用中发挥作用。
93 20
|
3月前
|
存储 Linux Shell
Linux进程概念-详细版(二)
在Linux进程概念-详细版(一)中我们解释了什么是进程,以及进程的各种状态,已经对进程有了一定的认识,那么这篇文章将会继续补全上篇文章剩余没有说到的,进程优先级,环境变量,程序地址空间,进程地址空间,以及调度队列。
65 0
|
3月前
|
Linux 调度 C语言
Linux进程概念-详细版(一)
子进程与父进程代码共享,其子进程直接用父进程的代码,其自己本身无代码,所以子进程无法改动代码,平时所说的修改是修改的数据。为什么要创建子进程:为了让其父子进程执行不同的代码块。子进程的数据相对于父进程是会进行写时拷贝(COW)。
67 0
|
6月前
|
存储 Linux 调度
【Linux】进程概念和进程状态
本文详细介绍了Linux系统中进程的核心概念与管理机制。从进程的定义出发,阐述了其作为操作系统资源管理的基本单位的重要性,并深入解析了task_struct结构体的内容及其在进程管理中的作用。同时,文章讲解了进程的基本操作(如获取PID、查看进程信息等)、父进程与子进程的关系(重点分析fork函数)、以及进程的三种主要状态(运行、阻塞、挂起)。此外,还探讨了Linux特有的进程状态表示和孤儿进程的处理方式。通过学习这些内容,读者可以更好地理解Linux进程的运行原理并优化系统性能。
217 4
|
6月前
|
存储 算法 数据处理
进程基础:概念、状态与生命周期
进程是操作系统进行资源分配和调度的基本单位,由程序段、数据段和进程控制块(PCB)组成。线程是进程中更小的执行单元,能独立运行且共享进程资源,具有轻量级和并发性特点。进程状态包括就绪、运行和阻塞,其生命周期分为创建、就绪、运行、阻塞和终止阶段。
333 2
|
Go 调度 开发者
[go 面试] 深入理解进程、线程和协程的概念及区别
[go 面试] 深入理解进程、线程和协程的概念及区别
|
分布式计算 JavaScript 前端开发
多线程、多进程、协程的概念、区别与联系
多线程、多进程、协程的概念、区别与联系
253 1
|
9月前
|
调度 开发者
核心概念解析:进程与线程的对比分析
在操作系统和计算机编程领域,进程和线程是两个基本而核心的概念。它们是程序执行和资源管理的基础,但它们之间存在显著的差异。本文将深入探讨进程与线程的区别,并分析它们在现代软件开发中的应用和重要性。
324 4
|
12月前
|
数据采集 消息中间件 并行计算
进程、线程与协程:并发执行的三种重要概念与应用
进程、线程与协程:并发执行的三种重要概念与应用
292 0