彻底理解进程

操作系统的”进程”很早就出现了,许多教科书上讲述这个概念总是晦涩难懂。计算机技术发展太快了,简单的概念经过无数次演化,也会变得复杂。我们追溯一下操作系统的发展历史,就能理解进程解决了什么问题、为什么这样设计。

1 操作系统的发展

1.2 手工操作阶段

第一代计算机使用真空管形成集成电路进行计算,使用磁鼓或磁芯作为存储器,穿孔卡片作为输入和输出介质,卡片上的孔代表机器指令或数据。

[En]

The first generation of computers used vacuum tubes to form integrated circuits for calculation, using magnetic drums or cores as storage, punched cards as input and output media, and holes on cards representing machine instructions or data.

程序员直接与硬件打交道,不需要操作系统。先将已穿孔的纸带装入输入机,然后启动输入机把程序和数据输入计算机内存,通过控制台开关启动计算程序。计算完毕,打印机输出计算结果。用户取走结果并卸下纸带后,才让下一个用户上机。这种手工操作方式有两个弊端:1. 用户独占全机,资源利用率低;2. CPU等待手工操作,利用不充分。

彻底理解进程
1.2 联机批处理系统

第二代计算机采用在线批处理系统,在主机和输入机之间增加了快速磁带机。在监控程序的自动控制下,计算机首先将用户的作业读入磁带,然后将磁带上的作业读入主存储器并输出计算结果。在完成最后一批作业后,监管程序从输入机输入另一批作业,并按照上述步骤重复处理。监控程序实现了作业到作业的自动切换,减少了人工操作时间,提高了计算机利用率,堪称操作系统的雏形。

[En]

The second generation computer adopts the on-line batch processing system, and a fast tape drive is added between the host and the input machine. under the automatic control of the supervision program, the computer first reads the user’s job into the tape, then reads the job on the tape into the host memory and outputs the calculation results. After completing the last batch of jobs, the supervision program inputs another batch of jobs from the input machine and repeats the processing according to the above steps. The monitor program realizes the automatic transfer from job to job, reduces the manual operation time, and improves the utilization rate of the computer, which can be regarded as the embryonic form of the operating system.

在等待作业输入和结果输出时,主机的CPU仍处于空闲状态,系统利用率依然不高。

彻底理解进程
1.3 多道程序系统

第三代计算机采用晶体管逻辑元件及快速磁芯存储器,计算机速度从每秒几千次提高到几十万次,主存储器的存贮量,从几千提高到10万以上。1958年,IBM公司制成了第一台全部使用晶体管的计算机RCA501型。

此时的磁带、硬盘等IO设备,完全跟不上高速CPU的脚步,CPU利用率非常低。人们引入了多道程序设计技术。把多个程序放入内存,并允许它们在CPU中交替运行,共享系统中的各种软硬件资源。当一道程序因IO请求而暂停运行时,CPU便立即转去运行另一道程序。多道程序设计技术使CPU得到充分利用,提高了整个系统的资源利用率和吞吐量。出现了作业调度管理、处理机管理、存储器管理、外部设备管理、文件系统管理等功能,这标志着操作系统日趋成熟。

彻底理解进程
1.4 分时系统

第四代计算机允许多个用户同时在线使用计算机,分时系统应运而生,进一步提高了系统的整体利用率。

[En]

The fourth generation computer allows multiple users to use the computer online at the same time, and the time-sharing system arises at the historic moment to further improve the overall utilization of the system.

彻底理解进程

如果用户的作业不能在分配的时间片内完成计算,则该作业被临时中断,处理器被分配给另一个作业,并等待下一轮继续。计算机的速度很快,作业的操作轮换得很快,给每个用户一种垄断计算机的错觉。用户可以通过自己的终端向系统发出控制命令,在完全人机交互的情况下完成作业的操作。

[En]

If a user’s job cannot complete the calculation within the allocated time slice, the job is temporarily interrupted, the processor is given to another job, and the next round is waited for it to continue. The speed of the computer is very fast, and the operation of the job rotates very fast, giving each user the illusion of monopolizing a computer. Users can issue control commands to the system through their own terminal to complete the operation of the job under the condition of full human-computer interaction.

1960年,麻省理工学院(MIT)开发了兼容分时系统(Compatible Time Sharing System),支持大型主机通过多个终端机来联机进行运算,并将结果从主机传输到终端机。此时终端机只具有输入输出的功能,本身不具任何运算或软件安装的能力。

为了强化大型主机的功能,让主机的资源让更多人来利用。1965年,由贝尔实验室(Bell)、麻省理工学院(MIT)及通用电器公司(GE)共同发起了MULTICS(多路信息计算系统)的计划,目标是让大型主机连接1000部终端机,支持300个用户同时使用。MULTICS项目是所有现代操作系统的鼻祖,并且首次提出了”进程”的概念。

进程是用户垄断计算机的假象的基础,每个用户的工作被包装为一个或多个进程。进程是具有独立功能的程序的动态执行过程,也是系统资源分配的独立实体。

[En]

Process is the basis of the illusion that users monopolize the computer, and each user’s job is packaged as one or more processes. A process is a dynamic execution process of a program with independent functions, and it is also an independent entity of system resource allocation.

2 低速的IO设备

1928年,德国工程师Fritz Pfleumer发明了存储模拟信号的录音磁带。工作原理是将粉碎的磁性颗粒用胶水粘在纸条上,但是纸条比较脆弱,录音磁带无法实用化。

1932年,IBM公司的奥地利裔工程师Gustav Tauschek发明了磁鼓存储器,长度为16英寸,有40个磁道,每分钟可旋转12500转,仅可以存储10KB数据。在磁芯存储器出现之前广泛用于计算机内存,被认为是硬盘驱动器的前身。磁鼓的优点为实用可靠、经济实惠,而缺点是存储容量太小、利用率低。

1948年,美国哈佛大学实验室的王安博士发明了磁芯存储器,次年又实现了磁芯存储器”读后即写”的技术。原理是在铁氧体磁环里穿进一根导线,导线中流过不同方向的电流时,可使磁环按两种不同方向磁化,代表”1″或”0″的信息便以磁场形式储存下来。最初的磁芯存储器只有几百个字节的容量。在20世纪70年代被广泛用作计算机的主存储器,直到Intel的半导体DRAM内存批量生产。

1952年,IBM公司发布了计算机业内的第一款磁带机,需要人工手动操作,比如装载、卸载和归档。

1956年,IBM公司制造了世界上第一块硬盘350RAMAC。盘片直径为24英寸,盘片数为50片,重量则是上百公斤,相当于两个冰箱的体积,储存容量只有5MB。

从早期的磁鼓到固态硬盘,IO设备速度提升了万倍,依然追不上CPU,根本原因是计算和存储的目标不一样。CPU的最重要指标是速度快;而存储设备则要容量大,其次是速度快,最后是造价低廉,这三点不可兼得。就好比两个运动员,一个练短跑,一个练长跑,对身体素质的要求不一样。

3 进程详解

我们以Linux系统为例,了解一下进程的基本构成。

3.1 进程的分类
  • 交互进程:由一个shell启动的进程,优先级较高,交互进程既可以在前台运行,也可以在后台运行。
  • 批处理:该进程与终端无关,是负责按顺序启动其他进程的进程序列。
    [En]

    batch process: this process has no connection with the terminal and is a process sequence that is responsible for starting other processes in sequence.*

  • 守护进程:在后台运行且不受任何终端控制的特殊进程,用于执行特定的系统任务。它一般在Linux启动时开始执行,系统关闭时才结束。
3.2 进程的组成

Linux内核把进程称为task,task_struct结构体是操作系统的进程控制块,包含着一个进程的所有信息。task_struct结构体非常复杂,感兴趣的朋友可以查阅文件 https://github.com/torvalds/linux/blob/master/include/linux/sched.h,以下列举了比较重要的字段:

  • 1)进程的标识

pid_t pid:进程的唯一标识
pid_t tgid:线程组的领头线程的pid成员的值

  • 2)进程调度信息

need_resched:调度标志
Nice:静态优先级
Counter:动态优先级;重新调度进程时会在run_queue中选出Counter值最大的进程。也代表该进程的时间片,运行中不断减少。
Policy:调度策略开始运行时被赋予的值。
rt_priority:实时优先级

  • 3)进程通信有关信息

unsigned long signal:进程接收到的信号。每位表示一种信号,共32种。
unsigned long blocked:进程所能接受信号的位掩码。
Spinlock_t sigmask_lock:信号掩码的自旋锁
Long blocked:信号掩码
Struct sem_undo semundo:为避免死锁而在信号量上设置的取消操作
Struct sem_queue
semsleeping:与信号量操作相关的等待队列
struct signal_struct *sig:信号处理函数

  • 4)上下文信息

struct desc_struct *ldt:进程关于CPU段式存储管理的局部描述符表的指针
struct thread_struct tss:任务状态段

  • 5)时间信息

Start_time:进程创建时间
Per_cpu_utime:进程在执行时在用户态上耗费的时间
Pre_cpu_stime:进程在执行时在系统态上耗费的时间
ITIMER_REAL:实时定时器,不论进程是否运行,都在实时更新
ITIMER_VIRTUAL:虚拟定时器,只有进程运行在用户态时才会更新
ITIMER_PROF:概况定时器,进程在运行处于用户态和系统态时更新

  • 6)地址空间/虚拟内存信息

struct mm_struct * mm:记录进程内存使用的信息

3.3 进程的内存分布

为了更加高效地使用内存,Linux系统采用了虚拟内存的方案,将物理内存和磁盘都映射为虚拟内存地址,为进程提供统一的地址空间。虚拟内存有三个优点:1)将内存当作磁盘的缓存,在内存中只保留常用数据,必要时从内存和磁盘之间交换数据。2)简化内存管理,为每个进程提供统一的地址空间。3)保护进程的内存空间不受其他进程影响。

每个进程都有单独的地址空间。一个进程不能访问另一个进程的变量和数据结构。如果希望一个进程访问另一个进程的资源,请使用进程间通信,如管道、文件、套接字等。

[En]

Each process has a separate address space. One process cannot access the variables and data structures of another process. If you want one process to access another process’s resources, use inter-process communication, such as pipes, files, sockets, etc.

进程的虚拟地址空间分为用户虚拟地址空间和内核虚拟地址空间,所有进程共享内核虚拟地址空间,每个进程有独立的用户虚拟地址空间。以32位Linux系统为例,共有4G的寻址能力。默认将高地址的1G空间分配给内核,称为内核空间,剩下的3G空间分配给进程使用,称为用户空间。用户空间从低地址到高地址空间包含5个部分:

彻底理解进程
  • 代码段(text segment):存放程序的可执行二进制代码。
  • 数据段(data segment):存放程序中已经初始化且初值不为0的全局变量和静态局部变量,数据段属于静态内存分配。
  • BSS段:存放未初始化的全局变量和静态局部变量;初值为0的全局变量和静态局部变量。
  • 堆(heap):用于存放程序运行时动态分配的内存段,可动态扩张或者缩减。
  • 栈(stack):由编译器自动分配释放,它存放函数内部声明的非静态局部变量,以及记录函数调用过程的相关维护信息(称为栈帧)。
3.4 进程的调度

每个CPU(或核心)在一个时间点上只能处理一个进程。操作系统调配CPU时间和其他资源,为进程分配一个状态,进程的状态随着环境要求而改变。进程运行的整个生命周期划分为六种状态:

  • Running:表示进程处在CPU的就绪队列中,运行态或者就绪态的进程
  • Disk Sleep:不可中断状态睡眠,一般表示进程正在跟硬件发送交互,并且交互过程中不允许被其他进程或中断打断
  • Zombie:僵尸进程,表示进程实际上已经结束了,但是父进程还没有回收它的资源(比如进程的描述符,PID等)
  • Interruptible Sleep:可中断状态睡眠,表示进程因等待某个事件而被系统挂起(阻塞态)。当进程等待的事件发生时,就会被唤醒并进入Running状态
  • Idle:空闲状态。用在不可中断睡眠的内核线程上。硬件交互导致的不可中断进程用D表示,但对某些内核线程来说,处在不可中断睡眠时有可能实际上并没有任何负载。
  • Stopped OR Traced:表示进程处于暂停或者跟踪状态。向一个进程发送SIGSTOP信号,它就会因响应这个号变成暂停状态(Stopped);向它发送SIGCONT信号,进程又会恢复运行(如果进程是终端里直接启动的,则需要用fg命令恢复到前台运行)。当用调试器调试一个进程时,在使用断点中断进程后,进程就会变成跟踪状态,这其实也是一种特殊的暂停状态,只不过可以用调试器来跟踪并按需要控制进程的运行。
  • EXIT:进程已经消亡

彻底理解进程

4 参考

https://www.linuxprobe.com/linux-system-programming.html
https://zhuanlan.zhihu.com/p/442909853
https://blog.csdn.net/qq_41209741/article/details/82870876

Original: https://www.cnblogs.com/xiaoyangjia/p/16615795.html
Author: 编码砖家
Title: 彻底理解进程

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/522831/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球