概念进程
一个已经加载到内存中的程序叫做进程(也可以叫做任务)

在Linux中使用【ps axj】可以查到正在运行的进程

在Linux中,称正在运行的程序叫做进程。

理解进程
一个操作系统不仅仅只能运行一个进程,可以同时运行多个进程。而有的进程是刚开始运行,有的是已经运行起来,有的是已经运行结束的。所以操作系统需要将进程管理起来——>先描述再组织。
先组织再描述
任何一个进程,在加载到内存形成真正的进程时候,操作系统会先创建描述进程(属性)的结构体对象——PCB(process ctrl block).
PCB本质:进程属性的集合(也是struct结构体)
【这个结构体的内容分类】
- 进程编号(标识符):描述本进程的唯一标识符,用来区别其他进程。
- 状态:任务状态,退出代码,退出信号等。
- 优先级:相对于其他进程的优先级。
- 程序计数器:程序中即将被执行的下一条指令的地址。
- 内存指针:包括程序代码和进程相关数据的指针,还有其他进程共享的内存块的指针
- 上下文数据:进程执行时处理器的寄存器中的数据
- I/O状态信息:包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表
- 记账信息:可能包括处理器时间中和,使用的时钟数总和,时间限制,记账号等等
- 其他数据
根据进程的PCB类型,为该进程创建对应的PCB对象。单独的PCB(描述该进程的对象)+该进程的代码和数据=进程。
所谓的进程,就是内核PCB数据结构对象和其代码和数据。
【解释】在将一段代码传入到内存中的时候,操作系统会将这个代码设置相对应的struct结构体对象,然后这个结构体对象中有一个指针,会指向这个代码和数据。也就是说,在内存中有这个代码的属性,和这个代码,这两个内容的和称为一个进程。
- 操作系统在管理这个进程的时候,不需要考虑进程相关的代码和数据,只需要管理这个进程的PCB数据结构对象即可

在操作系统中,对进程进行管理,变成了对链表等数据结构进行增删查改。
Linux中是如何管理进程
- 进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合
- PCB(process control block),Linux操作系统下的PCB是:task_struct.
- task_struct是Linux内核中的一种数据结构类型,它会被装载到RAM(内存)里并且包含着进程的信息。
tast_struct
https://www.cnblogs.com/tongyan2/p/5544887.html
问题:Linux是如何组织进程的?
Linux内容中,最基本的组织进程task_struct的方式,采用双向链表的方式。
查看进程
进程的信息通过 /proc 系统文件夹中查看
- 使用指令 ls /proc

PID:进程的id值
PPID:父进程id值
- 可以使用指令:ps axj指令查看进程信息
- ps ajx | head -1 查看进行信息的第一行
- ps axj | grep process 查看进行信息中包含process字样的行

#include<stdio.h>
#include<unistd.h>
int main()
{
while(1)
{
printf("process: \n");
sleep(1);
}
return 0;
}
使用vim编辑器编写这段代码。

调用man 3 sleep,在3号手册中了解到sleep()函数的头文件是#include<unistd.h>

使用./process就开始了一个进程。
![]()
调用指令ps axj | head -1 查看进程的属性头


- 查看进程的相关属性,PID是进程的ID属性,COMMAND表示进程运行时执行的是什么指令。
- grep会过滤后面相关的内容,而grep执行指令后自己也是一个进程,自身也携带了process关键字的
- 如果不想出现grep这个进程,可以再在这条指令后面添加grep -v grep【grep携带-v选项,即反向选择,即显示除没有‘搜寻字符串’内容的那一行。】
- 获取到进程的pid后,可以对这个进程进行操作了,例如:kill -9 176146——杀死这个进程


系统调用进程ID

- 每一个进程在被创建出来的时候,都会有自己的PID,操作系统会将每一个进程的PID存放在每一个进程的结构体task_struct中。
- ps axj这个指令是使用C语言写出的,其本质就是通过代码通过系统调用接口,然后遍历每一个进程的task_struct中的每一个属性,并将这些属性打印出来、
如何获取程序的PID?
- 系统会给用户提供一个系统调用接口:getpid();来获取进程的pid属性——进程标识符
- 使用系统二号手册来查看系统调用接口:man 2 getpid
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
// pid_t is int type
pid_t id = getpid();
while(1)
{
printf("process PID: %d\n", id);
sleep(1);
}
return 0;
}


- while :; do ps axj | head -1 ; ps axj | grep process | grep -v grep; echo "---------------------------------------------"; sleep 1; done
- 使用上述指令在一个新的会话中形成一个监控脚本,来获取进程的相关属性,这里主要为了查看进程的PID
- 使用getpid()在自己的代码中获取进程id和使用指令ps axj获取进程属性中的pid值相等。
- 每一次运行程序时,每一次进程id都会不同,这是操作系统在进程运行时随机分配的。
getpid(); 获取进程的id值
父进程
每一个进程都是由其父进程创建出来的
getppid(); 获取父进程的id值
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
// pid_t is int type
pid_t pid = getpid();
pid_t ppid = getppid();
while(1)
{
printf("process PID: %d---Father process PID: %d\n", pid, ppid);
sleep(1);
}
return 0;
}

使用系统调用和使用ps axj获取的进程id和父进程id是相同的。

运行多次实验发现,每一次的进程id都不同,而每一个父进程id都是同一个id值。

- 而这个一直不变的父进程就是bash进程
- 每一次登陆xshell时,操作系统都会重新创建一个bash进程,这个bash进程的pid也会改变
- 系统创建的bash进程会在终端形成命令行解释器
- 我们在命令行解释器下输入的所有的进程都是bash进程的子进程

2258

被折叠的 条评论
为什么被折叠?



