1 基本概念与基本操作
• 课本概念:程序的一个执行实例,正在执行的程序等
• 内核观点:担当分配系统资源(CPU时间,内存)的实体。
在教材中对进程的概念是运行起来的加载到内存的程序
但实际上并不只是这样
我们都知道在操作系统中会存在很多进程,这些进程需要被妥善管理,那么该怎么管理呢?
答案是:先描述(用结构体描述进程的相关属性),再组织(用数据结构(如链表)将众多结构体组织起来)
这样,对进程的管理就变成了对链表的增删查改
2 描述进程-PCB
基本概念
• 进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合。
• 课本上称之为PCB(process control block),Linux操作系统下的PCB是: task_struct
task_struct------PCB的一种
• 在Linux中描述进程的结构体叫做task_struct。
• task_struct是Linux内核的一种数据结构,它会被装载到RAM(内存)里并且包含着进程的信息。

由此,我们可以得出一个结论
进程=PCB(内核数据结构)+代码和数据
注意:
进程排队,本质其实就是让你的PCB节点进行排队
3 task_ struct
内容分类
• 标示符: 描述本进程的唯一标示符,用来区别其他进程。
• 状态: 任务状态,退出代码,退出信号等。
• 优先级: 相对于其他进程的优先级。
• 程序计数器: 程序中即将被执行的下一条指令的地址。
• 内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针。
• 上下文数据: 进程执行时处理器的寄存器中的数据。
• I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
• 记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
• 其他信息
• 在此我们只需了解一下task_ struct中的大致内容,具体详细信息后续会介绍
组织进程
所有运行在系统里的进程都以task_struct链表的形式存在内核里。

4 查看进程
1. 进程的信息可以通过/proc 系统文件夹查看
如:要获取PID为1的进程信息,你需要查看/proc/1 这个文件夹。

每一个进程都有其对应的标识符,通过系统调用获取进程标示符
cpp
#include<unistd.h>
getpid();


我们可以看到,当test进程正在运行时,我们可以看到他的标识符,当停止时,这个进程也就没有了

当test进程正在运行时,我们可以查看他的信息
在实际操作中,我们我们很少这样来查看进程,我们更多的是用下面这种方法来查看进程
2. 大多数进程信息同样可以使用ps这些用户级工具来获取
ps
cpp
ps axj //默认会显示当前系统内启动的所有进程

在实际使用中我们可以搭配grep行过滤等命令来查看具体的进程

cpp
ps axj | head -1 //只显示ps命令显示后的第一行 方便查看进程信息
ps axj | grep "test" //过滤出我们要查看的test进程
// &&将两个命令结合在一起
- UID:用户ID。
- PID:进程ID。
- PPID:父进程ID。
- C:CPU占用率。
- STIME:进程启动时间。
- TTY:终端设备。
- TIME:累计CPU时间。
- CMD:命令行。
5 父进程
接下来我们引入一个概念,父进程
cpp
getppid() //获得当前进程父进程的id
我们都知道Linux中有很多进程,但这些进程是怎么创建的呢?
Linux增多进程是通过父进程创建子进程的方式让子进程中的数据变多的


我们可以看到,每次test进程启动,其对应的id都会变,但为什么其父进程对应的ppid没有变呢?
事实上,我们在命令行中启动的命令/程序的时候都会变成进程,这些进程都是有统一的的父进程bash创建的子进程,我们的代码都是由子进程执行的
那我们可以创建自己的子进程吗?
当然可以,这就要引入fork函数了
6 通过系统调用创建进程-fork初识
运行 man fork 认识fork


• fork成功后有两个返回值
给父进程返回子进程pid
给子进程返回0
• 父子进程代码共享,数据各自开辟空间,私有一份(采用写时拷贝)


我们可以看到,该程序输出了两条语句,从中可以看出,第一条语句是父进程输出的,第二条语句是子进程输出的
• fork 之后通常要用 if 进行分流
这样可以使我们更清楚的看到两个进程的执行


到此,进程初识之进程查看就讲完了,怎么样,是不是感觉大脑里面多了很多新知识。
如果觉得博主讲的还可以的话,就请大家多多支持博主,收藏加关注,追更不迷路
如果觉得博主哪里讲的不到位或是有疏漏,还请大家多多指出,博主一定会加以改正
博语小屋将持续为您推出文章