Linux操作系统(计算机的哲学)中的进程

1 认识冯诺依曼系统

我们常见的计算机笔记本和不常见的计算机服务器大部分都遵循冯诺依曼系统。
在这里插入图片描述
我们所认识的计算机,都是由一个个的硬件组件组成。

  • 输入单元:键盘鼠标等
  • 中央处理器(CPU):包含运算器和控制器等
  • 输出单元:显示器,打印机等
    关于冯诺依曼
  • 存储器指的是内存
  • 不考虑缓存情况,CPU只能对内存进行读写,不能访问外设(输入和输出设备)
  • 外设要输出或者输出数据,也只能写入内存或者从内存中读取。
  • 所有设备都只能和内存打交道。

2 操作系统

2.1 概念

任何计算机系统都包含一个基本的程序集合,称为操作系统(OS),简单来说OS包括
内核(进程管理、内存管理、文件管理、驱动管理)
其他程序(函数库、shell程序等)

2.2 设计OS的目的

对上为用户程序(应用程序)提供一个良好的执行环境。
对下与硬件交互,管理所有的软硬件资源

在这里插入图片描述

2.3 定位

在整个计算机软硬件架构中,操作系统的定位是:搞管理的软件,那么类似学生的例子,比如要管理学生,
是要把学生描述起来,比如描述一个学生可以有学号、籍贯、电话等,那么管理学生其实并不是直接管理而是
把学生的信息录入学生管理系统,其实用面向对象的思想可以概括为:把学生共有的特性抽象出来,每个学生
其实是一个对象。

3 进程

3.1 进程的基本概念和描述进程

当我们把C/C++源代码编译运行是生成可执行程序。那么进程就是:进程对应的可执行程序 + 描述该进程各种属性信息的数据结构。
进程信息被放在一个叫做进程控制块的数据结构中,可以看做是进程属性的集合。
课本上称之为PCB(process control block),Linux操作系统下的PCB是:task_struct
task_struct是Linux内核的一种数据结构,它会被装载到内存里并且包含着属性信息。
task_ struct内容分类
标示符: 描述本进程的唯一标示符,用来区别其他进程。
状态: 任务状态,退出代码,退出信号等。
优先级: 相对于其他进程的优先级。
程序计数器: 程序中即将被执行的下一条指令的地址。
内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
上下文数据: 进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器]。 I/O状态信息: 包括显示的>I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
等。
可以在内核源代码里找到它。所有运行在系统里的进程都以task_struct链表的形式存在内核里。

3.2 如何组织进程

可以在内核源代码中找到它,所有运行在系统里的进程都以task_struct链表的形式存在内核里。
在这里插入图片描述
在这里插入图片描述
这个结构体是非常巨大的。

3.3 进程的基本操作

3.3.1 查看进程

1、ps aux

在这里插入图片描述

扫描二维码关注公众号,回复: 13086496 查看本文章

2、 ls /proc/
在这里插入图片描述
在/proc下查看具体某个进程的全部属性信息
在这里插入图片描述
3、 通过系统调用获得进程标识符
在这里插入图片描述

3.3.2 创建进程

通过系统调用fork(),创建进程。
在这里插入图片描述
在Linux下运行man fork可以认识下fork
fork没有参数
fork有两个返回值,这个很重要,如果创建成功给父进程(当前进程)返回创建的子进程的进程ID,给子进程返回0值,如果创建进程失败,给父进程返回值-1。
父进程和子进程代码是共享的,数据各自开辟空间私有一份(采用写时拷贝)
fork之后通常要用if进行分流,之后就可以不同的进程执行不同的任务,实现分流

下面是原汁原味的英文文档:

在这里插入图片描述

用系统调用fork创建进程的代码如下:

在这里插入图片描述

运行结果如下:

在这里插入图片描述

  • 那么下面有几个问题需要搞清楚。
  • 1、如何深刻理解进程创建呢?

一个进程在系统中被创建了,系统多了一个进程,就多了一个管理改进程的数据结构(OS内核做的事情) + 该进程对应的代码和数据(用户做的事)

  • 2、fork为什么会有两个返回值,如何深刻理解?

在这里插入图片描述

  • 3、fork后父子进程的执行顺序,代码数据在父子进程之间是怎样分配的?

进程数据 = 代码 + 数据
父进程创建子进程的时候代码是共享的,数据是各自私有一份的
代码是逻辑,一般是不能被修改的,数据是可读可写的,这也证实了上面说的fork那的的运行结果。
父和子谁先运行是由调度器决定的,看谁先排队,而且是有变化的,是由调度器的算法决定的。

在这里插入图片描述

3.3.3 进程的状态

为了搞清楚正在运行的进程是什么意思,我们需要知道进程的不同状态。一个进程可以有几个状态,在linux内核里,进程有时候也叫做任务。
进程的状态在Linux内核的源代码是是这样定义的:

在这里插入图片描述

  • 1、R运行状态(running):并不意味着进程一定在运行中,它表明进程要么是在运行中要么是在运行队列里。也就是说R状态的进程可以不在CPU上,R代表可以直接被CPU调度。
  • 2、S睡眠状态(sleeping):意味着进程在等待事件完成(这里的睡眠也叫做可中断睡眠(interruptible sleep)),举个栗子,看下面的操作图。
    在这里插入图片描述
    在这里插入图片描述

进程proc的状态是S(+代表不是后台进程可以被Ctrl + c终止)。因为printf()这个系统调用要把数据打印到显示器这个外设上,而显示器外设的速度是相当低的,CPU的速度是非常快的,那么大部分时间CPU都是在等待显示器完成工作。

在这里插入图片描述
在这里插入图片描述

上面这个情况就变成了R,因为死循环只在CPU上跑,不和外设打交道。
3、D磁盘休眠状态(Disk sleep):有时也叫做不可中断睡眠(uninterruptible sleep),也可叫做深度睡眠,S为浅度睡眠,比如进程要读取硬盘的数据(IO操作),先要找到数据,然后要拷贝一份给进程进入内存,此时进程在等待数据准备完事才可以操作。此时万一内存要是被其他进程占用完了,OS为了不让自己挂掉,要开始杀进程了,但是不能杀掉,D这个情况的进程,因为杀掉了,IO操作发生错误,为了避免这个情况发生,OS把D这个情况的进程标记为不可以杀掉的进程,这是一个硬盘不给我数据至死不休的状态,S,R都是可以被杀掉的。

4、T停止状态(stopped):可以通过发送SIGSTOP信号给进程,来停止进程。这个被暂停的进程可以通过接受SIGCONT信号让进程继续进行。
可以通过kill -l 查看信号代码

在这里插入图片描述

下面给出操作:后台运行进程proc 然后暂停使其状态变为T,再变为R

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5、X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。

6、Z(zombine)僵尸进程:僵死状态是一个比较特殊的状态。当进程退出并且父进程,没有读取到子进程退出的返回码是就会产生僵尸进程。
僵死(尸)进程会以终止状态保持在进程表时,并且会一直等待父进程读取退出状态码。
所以,只要子进程退出,父进程还在进行,但父进程没有读取子进程状态,子进程会进入Z状态。
危害:
进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程),你交给我的任务,我办的怎
么样了。可父进程如果一直不读取,那子进程就一直处于Z状态?是的!
那一个父进程创建了很多子进程,要是不回收,就会造成内存资源的泄露。那么既然有危害OS为什么还允许这个存在呢,因为父进程要读取子进程的退出信息不能立刻把子进程的资源还给OS。
总结一下,子进程退出,父进程还没读取子进程的退出状态的这段时间就是Z。
7 孤儿进程:父进程如果提前退出,子进程就称之为"孤儿进程"。
孤儿进程被1号init进程领养

来一张总结图

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/CZHLNN/article/details/113703616
今日推荐