进程的基本概念

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分区,从而为内存留出空间,这样减轻了内存的压力,但是降低了效率,使用效率换空间。

相关推荐
A.A呐26 分钟前
【Linux第一章】Linux介绍与指令
linux
Gui林27 分钟前
【GL004】Linux
linux
ö Constancy31 分钟前
Linux 使用gdb调试core文件
linux·c语言·vim
tang_vincent32 分钟前
linux下的spi开发与框架源码分析
linux
xiaozhiwise36 分钟前
Linux ASLR
linux
wellnw36 分钟前
[linux] linux c实现共享内存读写操作
linux·c语言
a_安徒生1 小时前
linux安装TDengine
linux·数据库·tdengine
追风赶月、1 小时前
【Linux】线程概念与线程控制
linux·运维·服务器
小字节,大梦想1 小时前
【Linux】重定向,dup
linux
blessing。。2 小时前
I2C学习
linux·单片机·嵌入式硬件·嵌入式