进程是什么
进程故名思意就是在计算机中正在进行中的程序。
我们知道操作系统对计算机中的所有程序是 先描述、在组织 。那么计算机中是如何对进程进行描述的?
描述进程-PCB
PCB(process control block)进程管理块。在计算机中,进程被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合。(Linux操作系统下的PCB是 task_struct :Linux 内核中的一种数据结构,被转载到RAM中 包含着进程的信息)
task_struct 内容:
- 标识符:描述进程的唯一标识符,用来区别其他进程;
- 状态:任务状态,退出信号,退出代码等;
- 优先级:相对于其他进程的优先级;
- 程序计数器:存放着程序中即将要被执行的下一跳指令;
- 内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针;
- 上下文数据:进程执行时处理器的寄存器中的数据
- I / O 状态信息:包含显示的I / O请求,分配给进程的 I / O 设备和被进程使用的文件列表;
- 记账信息:可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号;
组织进程
先描述、再组织,怎么组织呢?所有运行在系统里的进程都已 task_struct 链表的形式存在内核里;
CPU分时机制:切换调度进程,每个进程之运行很短的时间(时间片);
查看进程
在系统文件 /proc 中:
还可以通过命令 ps aux 来查看进程的详细信息:
进程描述符
上面的表中有一项叫做 PID 每一个进程都不一样,这个 PID叫做进程描述符。(PPID:父进程的 id)
通过系统调用获取进程标识符
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
int main(){
printf("pid:%d",getpid());
printf("ppid:%d",getppid());
return 0;
}
创建进程
通过复制调用进程(父进程)创建一个新的进程(子进程)。
复制父进程的PCB,和父进程运行相同的代码,一样的运行位置,处理一样的数据。
父子进程之间 代码共享,数据独有(虚拟内存地址相同,但是实际的物理地址不同)
#include <unistd.h>
pid_t fork(void);
/*
创建成功:
父进程:返回子进程PID
子进程:返回 0
创建失败:
父进程:返回 -1
*/
创建的子进程有什么用
1、分摊压力,CPU资源足够的情况下父子进程同时进行处理,效率更高
2、完成其他的任务(要进行分流)
查看进程状态
常见的进程状态有:R(运行态)、S(可中断睡眠态)、D(不可中断睡眠态)、T(停止状态)、Z(僵尸态)、X(死亡态)
ps aux 命令里面的 STAT 就是指该进程的状态;
僵尸进程(Z)
进程的僵死状态是一种非常特殊的状态,它的形成原因:
- 当子进程退出而父进程没有获取到子进程的退出状态,此时子进程的数据无法被释放,就成为了僵尸进程;
可见,无论对于哪种情况,只要父进程没有正确的处理子进程的返回信息,子进程都将停留在僵尸态,占据着内核资源;
僵尸进程的危害:1、占用内存,造成内存浪费,导致内存泄漏;2、占用系统资源;
解决僵尸进程:只有结束了其父进程,僵尸进程才会停止;
当父进程先于子进程退出后,子进程也会处于僵尸状态,但是会被1号进程回收,PPID变为1,此时称为孤儿进程;
进程优先级
CPU资源分配的先后顺序,就是指进程的优先权。优先权的高低,对于配置多任务环境的Linux很有用,可以大大改善系统性能。
几个重要的信息:
- UID:执行者的身份
- PID:这个进程的ID
- PPID:父进程的ID
- PRI:代表这个进程的优先级,PRI值越小,优先级越高
- NI:代表这个进程的 nice 值
PRI 的计算方法:PRI(新) = PRI(旧) + nice; nice 的取值范围是:-20 ~ 19 ,一共只有 40 个级别;
可以通过 top 命令来修改进程的优先级:top --> "r" --> 输入进程的PID --> 输出新的 nice 值