进程的简单介绍
进程是正在运行的程序的实例,程序就是一个可执行文件,占用磁盘的空间,但是不占用内存,只有当程序运行起来了,才会占用内存,且被分配资源。进程既是基本的分配单元,也是基本的执行单元。进程是操作系统提供的最古老也是最重要的抽象概念之一。
可以用一个程序来创建多个进程,进程是由内核定义的抽象实体,并为实体分配用以执行程序的各项系统资源。从内核的角度看,进程由用户内存空间和一系列内核数据结构组成,其中用户内存空间包含了程序代码和相关变量,内核数据结构则用于维护进程状态信息。
时间片由操作系统内核的调度程序分配给每个进程。首先,内核会给每个进程分配相等的初始时间片,然后每个进程轮番地执行相应的时间,当所有进程都处于时间片耗尽的状态时,内核会重新为每个进程计算并分配时间片,如此往复。
内核为每个进程分配一个PCB(Processing Control Block)进程控制块,维护进程相关的信息。Linux内核的进程控制块是一个task_struct结构体,以下为部分成员:
1.进程id:系统中每个进程有唯一的id
2.进程的状态:有就绪、运行、挂起、停止等状态
3.进程切换时需要保存和恢复的一些CPU寄存器
4.描述虚拟地址空间的信息
5.描述控制终端的信息
6.当前工作目录
7.umask掩码
8.文件描述符表,包含很多指向file结构体的指针
9.和信号相关的信息
10.用户id和组id
11.进程可以使用的资源上限
每个进程都由进程号来标识,其类型为pid_t(整型),进程号范围0-32767.进程号总是唯一的。
进程的状态
进程状态反映进程执行过程的变化。在三态模型中,进程状态分为三个基本状态,即就绪态、运行态、阻塞态。
运行态:进程占用CPU正在运行。
就绪态:进程具备运行条件,等待系统分配CPU以便运行。在一个系统中处于就绪状态的进程可能有多个,通常将它们排成一个队列,称为就绪队列。
阻塞态:又称为等待态或睡眠态,指进程不具备运行条件,正在等待某个事件的完成。
进程相关命令
ps aux / ajx
a:显示终端上的所有进程,包括其他用户的进程
u:显示进程的详细信息
x:显示没有控制终端的进程
j:列出与作业控制相关的信息
通过tty
能够显示当前终端信息,能够看到此时有一个正在运行的进程就是该终端。
其中有一列是STAT,代表进程状态,具备以下取值
D 不可终端
R 正在运行,或在队列中的进程
S 处于休眠状态
T 停止或被追踪
Z 僵尸进程
X 死掉的进程
< 高优先级
N 低优先级
s 包含子进程
- 位于前台的进程组
fan 10626 0.0 0.0 39108 3604 pts/2 R+ 17:53 0:00 ps aux
所以这个终端进程的R+代表正在运行且位于前台的进程。
top
实时显示进程动态,可以加上-d来指定显示信息更新的时间间隔。
按一下按键可以对显示结果进行排序:
M 根据内存使用量排序
P 根据CPU占有率排序
T 根据进程运行时间长短排序
U 根据用户名来筛选排序
K 输入指定的PID杀死进程
按下U,会显示需要显示那个用户的进程,输入fan,就会筛选出fan的进程。
//杀死进程相关命令
kill -l //列出所以信号
kill -9 进程ID
killall name //根据进程名杀死进程
进程的创建
系统运行一个进程创建新进程,新进程即为子进程,子进程还可以创建新的子进程,形成进程树结构模型。
#include <sts/types.h>
#include <unistd.h>
pid_t fork(void);
返回值:
- 成功:会返回两次,在子进程当中返回0,在父进程当中返回子进程ID。
- 失败:返回-1 。存在两个原因:
1.系统进程数达到上限,errno被设置为EAGAIN;
2.系统内存不足,errno的值被设置为ENOMEM。
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main(){
pid_t pid = fork();
if (pid > 0)
printf("我是父进程,pid=%d, ppid=%d\n",getpid(), getppid());
else if (pid == 0)
printf("我是子进程,pid=%d, ppid=%d\n",getpid(), getppid());
for(int i = 0; i < 5; ++i){
printf("i = %d, pid=%d\n",i,getpid());
sleep(1);
}
return 0;
}
测试代码如上所,getpid函数用来获得进程号,getppid用来获得父进程号。
运行结果如上所示,父进程的id是47787,它的父进程ID是12533 。通过命令ps aux
查看12533就是终端的ID。
新创建出来的子进程ID为47788,它的父进程ID是47787。然后发现它们在交替运行。