Linux进程初识:OS基础、fork函数创建进程、进程排队和进程状态讲解

目录

1、冯诺伊曼体系结构

问题一:为什么在体系结构中存在存储器(内存)?

存储单元总结:

问题二:为什么程序在运行的时候,必须把程序先加载到内存?

问题三:请解释,从你登录上qq开始和某位朋友聊天开始,数据的流动过程。

2、操作系统

2.1操作系统的概念:

我们首先要明白什么是管理:

2.2为什么要有操作系统?

2.3操作系统如何保证稳定和安全呢?(利用系统调用函数解决)

库函数和系统调用的关系:

3、那到底什么是进程呢?(重要!)

3.1、什么程序加载到内存,变成一个进程之后,我们要给每一个进程形成一个PCB对象呢?

3.2、PCB进程标识符:

4、fork函数初识

4.1、fork函数的作用:

4.2、使用方法(一般都用if分流)

4.3、关于fork函数的灵魂三问:

1、为什么给父进程返回子进程的pid,给子进程返回0?

2、fork函数为什么会返回两次?

3、这里的id为什么会同时满足 == 0 又满足>0呢?

问题:为什么我们在磁盘上将一个程序删了,这个程序还能运行呢?

5、进程排队:

6、进程状态:

6、1那什么是挂起状态呢?

6.2、Linux下具体的进程状态:

D状态深度睡眠又是什么呢?

6.3、为什么要有Z状态?

6.4、什么是僵尸Z状态?

6.5、僵尸进程危害:

7、什么是孤儿进程?

1、冯诺伊曼体系结构

截至目前,我们所认识的计算机,都是由一个个的硬件组件组成

  • 输入单元:包括键盘, 鼠标,扫描仪, 写板等
  • 中央处理器(CPU):含有运算器和控制器
  • 输出单元:显示器,打印机等
  • 存储器:指的是内存(掉电易失)
  • 运算器主要进行算术运算(加减乘除)和逻辑运算(判断真假)

设备是互相连接的,目的是让设备之间数据流动,本质是让设备之间进行数据的来回拷贝(拷贝的整体速度,是决定计算机效率的重要指标

问题一:为什么在体系结构中存在存储器(内存)?

输入输出设备的运行速度就会拖累cpu的运行速度,跟木桶原理一个道理,那存储器并没有解决短板的问题,那怎么提高运行速度呢?

我们把内存看做一个非常大的缓存,介于设备和CPU之间
利用预存和缓存的机制,将计算机的效率最终变成了内存效率为主

存储单元总结:

距离CPU越近的存储单元,效率越高,造价贵,单体容量越小

距离CPU越远的存储单元,效率越低,造价便宜,单体容量大

所以内存的引入,可以让我们的计算机效率不错,且价格比较便宜,这样我们才能买的起电脑

问题二:为什么程序在运行的时候,必须把程序先加载到内存?

因为冯诺依曼体系决定的!

在数据层面,CPU只和内存打交道;外设只和内存打交道

关于冯诺依曼,必须强调几点:
这里的存储器指的是内存
不考虑缓存情况,这里的CPU能且只能对内存进行读写,不能访问外设(输入或输出设备)
外设(输入或输出设备)要输入或者输出数据,也只能写入内存或者从内存中读取。
一句话,所有设备都只能直接和内存打交道

对冯诺依曼的理解,不能停留在概念上,要深入到对软件数据流理解上,

问题三:请解释,从你登录上qq开始和某位朋友聊天开始,数据的流动过程。

我们先通过键盘输入消息,然后加载到内存,CPU从内存中读取数据,进行加密和计算后再放到内存,显示器(显示消息到屏幕上)和网卡(发送数据到网络)再从内存中读取数据。(忽略网络部分处理细节)

        朋友电脑的网卡从网络上获取到了我们发送的数据,然后加载到内存,CPU从内存中读取数据,进行解密和计算后再放到内存,显示器再从内存读取相关的数据,显示到屏幕上。

总的来说,就是外设->内存->CPU->内存->外设

2、操作系统

2.1操作系统的概念:

操作系统是一个进行软硬件资源管理软件

我们首先要明白什么是管理

管理就是做决策+做执行。

管理者和被管理者,并不需要见面,管理的本质是对人的信息(数据)做管理。

管理者的核心工作是做决策,根据数据做决策。

总结为六字真言:

先描述,再组织

语言的本质就是对数据的管理

2.2为什么要有操作系统?

对下管理好软硬件资源(手段),对上提供一个良好(稳定、高效、安全)的运行环境(目的)

2.3操作系统如何保证稳定和安全呢?(利用系统调用函数解决)

任何人不得访问操作系统中的任何数据,需要利用系统调用的函数

不能直接越过操作系统!系统调用接口很重要

所谓的系统调用接口,其实就是函数,用C语言设计的函数,由操作系统提供:系统调用函数

库函数和系统调用的关系:

只要库函数调用了系统调用,他们两个就必然是上下层的关系,库函数在上,系统调用在下

3、那到底什么是进程呢?(重要!)

进程 = 内核PCB对象(内核的数据结构) + 可执行程序

这里的PCB到底是何方神圣呢?进程控制块(process control block)

在Linux环境下,PCB就是task_struct,存储进程的所有属性,操作系统内部的数据

未来,所有对进程的控制和操作,都只和进程的PCB有关,和进程的可执行程序没有关系

我们所说的让一个进程去排队,本质上是让PCB去排队,而不是让可执行程序去排队

对进程的管理,转换为对PCB对象的管理

3.1、什么程序加载到内存,变成一个进程之后,我们要给每一个进程形成一个PCB对象呢?

因为操作系统要进行管理!(先描述,再组织)

PCB这些内容都是在操作系统内部的数据

task_ struct内容分类

标示符: 描述本进程的唯一标示符,用来区别其他进程。
状态: 任务状态,退出代码,退出信号等。
优先级: 相对于其他进程的优先级。
程序计数器: 程序中即将被执行的下一条指令的地址。
内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
上下文数据: 进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器]。
I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
其他信息

3.2、PCB进程标识符:

下面主要讲解标识符,描述进程的唯一标识符,用来区别其他进程

getpid是我们第一个学习的系统调用函数,用来获得该进程的标识符。

每一次启动进程的pid几乎都会变化,因为我的进程是一个新的进程!

一般在Linux中,普通进程,都有他的父进程!

通过系统调用获取进程标示符
进程id(PID)
父进程id(PPID)

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
printf("pid: %d\n", getpid());
printf("ppid: %d\n", getppid());
return 0;
}

4、fork函数初识

4.1、fork函数的作用:

通过系统调用创建进程。它的作用是从已经存在的进程中创建一个子进程,而原进程称为父进程

4.2、使用方法(一般都用if分流)

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
int ret = fork();
if(ret < 0){
perror("fork");
return 1;
}
else if(ret == 0){ //child
printf("I am child : %d!, ret: %d\n", getpid(), ret);
}else{ //father
printf("I am father : %d!, ret: %d\n", getpid(), ret);
}
sleep(1);
return 0;
}

4.3、关于fork函数的灵魂三问:

1、为什么给父进程返回子进程的pid,给子进程返回0?

  • 在‌父进程中‌,fork函数返回新创建子进程的进程ID。这是因为父进程需要通过这个返回值来跟踪和管理其创建的子进程。
  • 在‌子进程中‌,fork函数返回0。这是因为子进程可以通过这个返回值来判断它是否成功创建,并且由于子进程只有一个父进程,它的ID可以通过getppid()获得父进程的ID,而子进程的ID(虽然与父进程ID不同)在fork函数返回时已经被系统内部记录下来。

父进程会有多个子进程,但是子进程只会有一个父进程,一对多的关系

2、fork函数为什么会返回两次?

当fork函数被调用时,它会创建一个新的子进程,这个子进程是父进程的一个复制品,它们共享相同的代码段和部分数据段。由于子进程是父进程的一个副本,因此它们都会执行fork函数之后的代码。这就导致了fork函数在父进程和子进程中都会“返回”,但返回的值不同

fork之后,我们的父和子都会进行,代码共享,一般而言,我们想让父子做不同的事情。调用fork函数,会返回不同的值分别给父子进程

父子进程执行不同的代码块

3、这里的id为什么会同时满足 == 0 又满足>0呢?

这是因为有两个进程,进程之间是具有独立性,互相不能影响!

问题:为什么我们在磁盘上将一个程序删了,这个程序还能运行呢?

我们在运行一个程序时,本质是把程序从磁盘拷贝到内存,换句话来说就是你把这个程序在磁盘上删了,但是这个程序比较小,已经拷贝到内存,在内存上运行了,成为一个进程,就与磁盘上的程序没有关系了

5、进程排队:

进程为什么会排队呢?一定是在等待某种“资源”,比如下面的scanf就需要等待键盘给他传输资源。

只要是排队,一定是进程的task_struct进行排队。

6、进程状态:

教材上关于进程状态的表述:运行、阻塞、挂起

所谓的状态,本质就是一个整形变量,在task_struct中的一个整型变量

状态决定了什么?决定了你的后续动作,Linux中可能会存在多个进程都要根据它的状态执行后续动作(进程开始排队了!)

当我们的进程在进行等待软硬件资源的时候,资源如果没有就绪,我们的进程task_struct只能1、将自己设置为阻塞状态2、将自己的PCB连入等待的资源提供的等待队列。

状态的变迁,引起的是PCB会被OS变迁到不同的队列当中。

当我们的软硬件资源准备就绪后,进程状态就会从阻塞状态调整到运行状态!

6、1那什么是挂起状态呢?

我们这里主要讲的是阻塞挂起,这个状态的前提是计算机资源比较吃紧了

挂起状态就是将数据从内存,换出到磁盘上面 ,当计算机资源恢复后,数据会从外设转入到内存中

6.2、Linux下具体的进程状态:

为了弄明白正在运行的进程是什么意思,我们需要知道进程的不同状态。一个进程可以有几个状态下面代码是状态在kernel源代码里定义:

static const char * const task_state_array[] = {
"R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */
"t (tracing stop)", /* 8 */
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */
};
  • R运行状态(running): 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
  • S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep))。
  • D磁盘休眠状态(Disk sleep)有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。
  • T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的程序可以通过发送 SIGCONT 信号让进程继续运行。
  • X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态

S状态其实与操作系统中的阻塞状态(等待某种资源)是一致的!!!

D状态深度睡眠又是什么呢?和S睡眠有什么区别?

深度睡眠,不可中断睡眠。

相当于给进程一个免死金牌,我们要知道在Linux环境下,在操作系统逼急的时候,是会杀掉进程!如果这个进程很重要,就会造成很大的损失,因此这个D状态就相当于给了进程一个免死金牌,不会被进程所杀掉。

注意D状态依旧是阻塞状态

kill -19 pid 就会让一个进程进入T状态,也就是暂停状态

继续运行就是 kill -18 pid

子进程最终的状态都是Z

注意状态标识后面有+,就代表是前台进程,可以直接^C杀死,但是如果没有+,就说明这个进程变成了后台进程,不能用^C杀死,只能kill-9方法

后台进程,我们用普通的^C是停止不掉的,那怎么停止呢?

我们可以使用这样的命令:kill -9 pid(该进程的pid)

6.3、为什么要有Z状态?

创建进程是希望这个进程给用户完成工作的,子进程必须得有结果数据返回给父进程

6.4、什么是僵尸Z状态?

僵死状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程(使用wait()系统调用,后面讲)
没有读取到子进程退出的返回代码时就会产生僵死(尸)进程
僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。
所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态

6.5、僵尸进程危害:

进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程),你交给我的任务,我办的怎
么样了。可父进程如果一直不读取,那子进程就一直处于Z状态?是的!
维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话
说,Z状态一直不退出,PCB一直都要维护?是的!
那一个父进程创建了很多子进程,就是不回收,是不是就会造成内存资源的浪费?也就会造成内存的泄露!

7、什么是孤儿进程?

父进程如果提前退出,那么子进程后退出,进入Z之后,那该如何处理呢?
父进程先退出,子进程就称之为“孤儿进程”

评论 29
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

可涵不会debug

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值