进程的基本概念

1.冯诺依曼体系结构

我们常见的计算机大都遵循冯诺依曼体系结构

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

输入单元:键盘,鼠标等等

CPU

输出单元:显示器。打印机,音箱等等

关于冯诺依曼架构的特点:

储存器指的是内存

CPU只能对内存进行读写,不能访问外设

外设要输入或输出数据,也只能写入内存或从内存中读写

数据要在计算机结构进行传输,从一个设备到另一个设备,本质上是数据的拷贝,设备之间的拷贝效率决定了计算机的整体效率,当我们运算数据时,CPU直接从储存器读取数据,减少了数据从输入设备到CPU的传输时间,如果没有了储存器,直接从输入设备直接把数据传给CPU,那么CPU的运算效率远远大于输入设备的传输效率,这样计算机的整体效率就取决与数据传输的效率,就很慢了,所以这就是冯诺依曼的优秀之处

2.操作系统

概念:任何计算机都包含一个基本的程序集合,称为操作系统(OS),操作系统包括

内核(进程管理,内存管理,文件管理,驱动管理)

其他程序(例如函数库,shell库)

操作系统是管理硬件之间数据传输的软件

3.进程

1.进程的概念

什么是进程?

进程就是PCB+代码和数据

当我们要执行一个可执行文件时,会先把可执行文件从磁盘中拷贝到内存中,然后对应生成一个pcb结构体,也叫做进程控制块,然后cpu通过管理pcb的属性,对可执行文件进行管理,一个进程一定有对应的pcb,

操作系统要对进程先描述,再组织,描述就是用pcb描述进程的属性,然后把pcb组织起来管理,操作系统中可以同时存在很多进程,然后多个pcb结构体组成链表数据结构或者其他数据结构方便管理,所以对进程的管理就变成了对链表的管理,

进程=pcb+代码和数据,在linux操作系统中,pcb对应的具体名字叫做task_struct(进程控制块),

如何理解进程动态运行?

只要task_struct在不同的队列中就可以访问不同的资源,

2.进程的task_struct属性

1.启动进程

./xxx(可执行文件),本质上是让系统创建进程并运行,

在linux运行的大部分指令,本质上都是一个进程,例如:ll pwd touhc file

2.进程pid

每个进程都有自己的唯一标识符,叫做进程pid,

用ps axj命令可以查看所有正在运行的进程,ps axj | head -1可以只显示第一行,显示对应的目录,用&&可以两条指令一起执行,ps axj | grep process 可以找到我们需要看的进程,所以我们可以这样写

ps axj |head -1&& ps axj |grep process

每个进程都有唯一的pid,如果我们想自己获得对应进程的pid该怎么写?

3.getpid()

获得对应的进程pid,可以调用对应的getpid()函数

getpid的返回值是pid_t,实际就是封装的无符号整形,

kill -9 getpid可以结束进程

4.进程创建的代码方式

进程分为子进程和父进程,分别有对应的pid和ppid,getppid可以获得父进程pid,一个父进程可以构造出很多个子进程,父进程的代码和数据是从磁盘中加载到内存中的,而子进程的代码是直接拷贝的父进程的,进程都是独立的,

复制代码
 #include <stdio.h>
 18 #include <unistd.h>
 19 #include <sys/types.h>
 20 
 21 int main() {
 22     pid_t pid = fork();
 23 
 24     if (pid < 0) {
 25         // fork失败
 26         perror("fork failed");
 27         return 1;
 28     } else if (pid == 0) {
 29         // 子进程
 30         printf("I am the child process  PID %d PPID  %d\n", getpid(), getppid());
 31     } else {
 32         // 父进程
 33         printf("I am the parent process PID %d PPID is %d\n", getpid(), pid);                                                
 34     }
 35     return 0;
 36 }

fork函数包含在usistd.h,sys/types.h中,fork函数可以用来创建一个新进程,成为子进程,它是调用父进程的副本,如果fork返回-1,也就是小于0的数,就是创建进程失败,如果返回0,则创建的是子进程,如果返回值大于0,那么创建的是父进程,

3.进程的状态

一个进程可以有几种状态,比如:

R(running)表示运行状态,并不意味着进程在运行状态,他表示进程要么在运行,要么在运行队列中

S(sleeping)表示睡眠状态,意味着进程在等待事件完成

D(Disk sleep),是linux系统特有的一种状态,也叫不可中断状态,这个状态的进程通常在等待IO的结束,

T/t(stopped)表示停止状态,比如我们运行一个程序,在断点处暂停,那么这个进程就是T/t状态,

z(zombie)表示僵尸进程,一个进程已经运行完毕,但是要维持自己的退出信息,在自己的task_struct 中会记录退出信息,等父进程来读取,如果父进程没有读取,那么这个进程就一直存在,成为僵尸进程,

父进程读取子进程的退出信息要调用wati()或waitpid()函数

当一个进程结束时,会记录自己的退出信息在task_struct中,然后释放代码和数据,而退出信息需要等到父进程读取后,才会释放,所以僵尸进程存在会造成内存泄漏,

我们直接在命令行里启动的进程,他的父进程是bash,bash会自动回收结束的进程, 所以不会产生僵尸进程,

4.孤儿进程

父进程如果先退出,其子进程还在运行,那么子进程就变成了孤儿进程,孤儿进程通常由操作系统接管

孤儿进程导致的一些问题:

1.资源占用,如果孤儿进程没有被适当地终止,它们可能会继续占用系统资源,如内存和CPU时间。

2.数据不一致,如果孤儿进程负责某些数据的更新或维护,那么在父进程终止后,这些数据可能会处于不一致的状态。

3.错误处理,孤儿进程可能无法正确处理错误,因为它们无法将错误信息传递给父进程。

5.进程的阻塞,挂起和运行

运行态

当cpu要运行一系列的进程时,他不会一个进程一直运行到结束,而是调度运行,cpu中有一个运行队列

cpu运行进程的方法是通过是通过调度算法管理的

当进程在运行中或者运行队列中都是R状态的

比如说cpu可以基于时间片进行轮转调度的,让多个进程以切换的方式进行调度,在一个时间段中同时推进进程,叫做并发,

在同一时刻都有多个进程在运行,叫做并行

进程在切换时,cpu中的寄存器,会保存进程的上下文数据,

阻塞态

阻塞态也称为等待态,指进程因等待某些事件(如输入/输出操作、信号量、锁等)而暂停运行

特点:

阻塞态无法被调度运行,因为他们在等待某个外部事件

挂起态

挂起态是指进程因为某些原因被操作系统暂时停止执行状态,在这种状态下,进程的所有活动被暂停,

进程的数据和代码会被保存到磁盘的swaps分区,从而为内存留出空间,这样减轻了内存的压力,但是降低了效率,使用效率换空间。

相关推荐
朱小弟cs65 小时前
Orange的运维学习日记--41.Ansible基础入门
linux·运维·学习·ci/cd·自动化·ansible·devops
CIb0la5 小时前
kali linux 2025.2安装WPS并设置无报错的详细步骤
linux·运维·wps
醉方休6 小时前
Node.js 精选:50 款文件处理与开发环境工具库
linux·运维·node.js
代码老y7 小时前
从裸机到云原生:Linux 操作系统实战进阶的“四维跃迁”
linux·运维·云原生
CMCST8 小时前
CentOS 7.9 升级 GLibc 2.34
linux·运维·centos
xiep14383335108 小时前
Rocky Linux 10 部署 Kafka 集群
linux·运维·kafka
笨鸟要努力12 小时前
Ubuntu 全盘备份
linux·运维·ubuntu
ChironW12 小时前
Ubuntu 22.04 离线环境下完整安装 Anaconda、CUDA 12.1、NVIDIA 驱动及 cuDNN 8.9.3 教程
linux·运维·人工智能·深度学习·yolo·ubuntu
轻松Ai享生活13 小时前
linux 日志详解
linux
前端老鹰13 小时前
CSS counter-reset 与 counter-increment:用 CSS 实现自动编号的黑科技
前端·css·html