【Linux】进程概念(二):PCB,ps 和 fork
📝前言:
上篇文章我们简单介绍了冯诺依曼体系结构和操作系统,这篇文章我们来讲讲进程的基本概念和基本操作
🎬个人简介:努力学习ing
📋个人专栏:Linux
🎀CSDN主页 愚润求学
🌄其他专栏:C++学习笔记,C语言入门基础,python入门基础,C++刷题专栏
目录
- 一,什么是进程
- 二,PCB
- task_struct
- 三,查看进程
- ps
- -axj选项组合
- /proc
- 系统调用进程标识符
- 杀掉进程
- 四,创建进程
- fork初识
- 子进程和父进程的关系
- 使用示例
- 1 简单示例
- 具体理解执行过程
一,什么是进程
在Linux操作系统中,进程(Process) 是程序执行时的基本单位,也是系统资源分配和调度的核心对象。
- 程序 vs 进程
- 程序:存储在磁盘上的静态可执行文件(如二进制文件或脚本)。
- 进程:程序被加载到内存并开始执行后的动态实例。一个程序可以对应多个进程(例如同时运行多个
vim
编辑器)。
进程由:程序代码,数据,进程控制块(PCB)组成。
进程 = PCB + 自己的代码和数据
很抽象,我们可以从进程的作用来理解:
进程是操作系统进行资源分配和调度的基本单位。操作系统会为每个进程分配独立的内存空间、CPU 时间片、文件描述符等资源,以确保各个进程能够独立、并发地运行,从而提高系统的资源利用率和处理能力。多个进程可以同时运行在计算机系统中,它们之间可以通过进程间通信(IPC)机制进行数据交换和协同工作,以完成更复杂的任务。
二,PCB
PCB(程序控制块)是操作系统用于管理进程的核心数据结构,包含了进程的各种信息,如进程 ID、进程状态、优先级、资源分配情况等(是进程属性的集合)。
Linux操作系统下的PCB是: 一个名为task_struct
的结构体,它会被装载到RAM(内存)里。
task_struct
task_struct
中主要包括:
- 标示符:描述本进程的唯⼀标示符,用来区别其他进程。
- 状态: 任务状态,退出代码,退出信号等。
- 优先级: 相对于其他进程的优先级。
- 程序计数器: 程序中即将被执⾏的下⼀条指令的地址。
- 内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
- 上下⽂数据: 进程执⾏时处理器的寄存器中的数据[休学例⼦,要加图CPU,寄存器]。
- I/O状态信息: 包括显⽰的I/O请求,分配给进程的I∕O设备和被进程使⽤的⽂件列表。
- 记账信息: 可能包括处理器时间总和,使⽤的时钟数总和,时间限制,记账号等
- 其他信息…
进程的组织:所有运⾏在系统⾥的进程都以task_struct
链表的形式存在内核⾥。
三,查看进程
ps
ps
命令默认显示的是当前机器(即你正在操作的这台计算机)的进程状态
常用选项:
-e
:显示所有进程,而不仅仅是与当前终端关联的进程-f
:显示进程的详细信息
示例:
UID
:启动进程的用户 IDPID
:进程标识符PPID
:该进程的父进程的 PIDC
:CPU 使用率STIME
:进程的启动时间TTY
: 表示进程所关联的终端设备TIME
:表示进程自启动以来累计使用 CPU 的时间CMD
:显示的是启动该进程所执行的命令,bash 进程,CMD 列显示为 bash,这表明该进程是一个 Bash shell 实例
我们可以发现:
ps -f
也是一个进程,也就是说: 我们历史上执行的所有指令,工具,程序,运行起来,全部都是进程- 我们在
bash
进程(也就是我们这个命令行)所创建的进程的父进程都有bash
,os会给每一个登陆用户分配一个bash
当我们在机器上运行一个.c
文件(可用while(1)
的方式保持一直执行),然后就可以查看到对应的进程:
可以看到,grep
也是一个进程,印证了我们上面的发现1
-axj选项组合
如:
head -1
可以输出表头STAT
代表进程状态&&
和;
可以分隔多条命令
/proc
进程的信息也可以通过 /proc
系统⽂件夹查看。
在 /proc
文件夹下,每个进程都有一个以其进程 ID(PID)命名的子目录。
如,查看PID为60592的进程的相关信息目录ls ./proc/60592
:
cwd
:指向进程启动时的当前工作目录(相对路径的起点),创建文件等操作,如果不带路径,就会在cwd
这个路径下创建。cd
操作本质上就是调用了chdir
函数来改变当前cwd
exe
:可执行文件,当exe
被删掉的时候还会有进程是因为:exe已经加载到内存中了,删掉的是磁盘上储存的exe
系统调用进程标识符
系统调用获取进程标识符:getpid()
,getppid()
(都是库函数对系统调用的封装)
运行结果:
重新启动进程,会重新想内存加载,pid是会改变的。
杀掉进程
Ctrl + c
:比如程序在执行while(1)
的时候一直刷屏,执行Ctrl + c
就是杀掉进程kill -9 + 进程对应的PID
:杀掉PID对应的进程,这里的9
代表信号
四,创建进程
fork初识
fork
是复制进程的函数,程序一开始就会产生一个进程,当这个进程(代码)执行到fork()
时,fork
就会复制一份原来的进程(即就是创建一个新进程,我们称子进程,而原来的进程我们称为父进程),此时父子进程是共存的,他们一起向下执行代码。
即:调用fork
函数之后,是两个进程同时执行fork
函数之后的代码(拥有各自独立的执行流),而之前的代码已经由父进程执行完毕。
fork
的返回值:
成功:子进程中返回: 0
,父进程中返回:子进程 PID。
错误:返回一个-1
子进程和父进程的关系
子进程和父进程的关系是什么呢?
- 因为父进程和子进程的关系是:1 : n(一对多),每个子进程只有一个父进程,但是父进程可以有多个子进程,所以父进程需要通过不同的pid区分不同的子进程
- 进程具有独立性,即使父进程挂了,子进程也不会挂
- 父进程和子进程的代码共享,数据也共享,只有当其中有一个进程要修改数据的时候,底层会进行数据拷贝,子一份,父一份,然后让要修改的目标进程进行修改(写时拷贝,各自私有一份)
使用示例
1 简单示例
代码:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{int ret = fork();printf("hello proc : %d!, ret: %d\n", getpid(), ret);sleep(1);return 0;
}
运行结果:
很明显这里fork有两个返回值,一个返回给父进程,一个返回给子进程。第一条打印语句是父进程的执行结果,第二条是子进程的。
具体理解执行过程
这里有一篇文章 fork函数讲解 写的特别好,我就不过多赘述了
🌈我的分享也就到此结束啦🌈
要是我的分享也能对你的学习起到帮助,那简直是太酷啦!
若有不足,还请大家多多指正,我们一起学习交流!
📢公主,王子:点赞👍→收藏⭐→关注🔍
感谢大家的观看和支持!祝大家都能得偿所愿,天天开心!!!