1.多进程
引入目的:让多个任务实现并发执行
并发执行:同一时间只有一个进程执行,通过时间轮询调度多个进程,由于时间每个进程所用时间极短,所以宏观表现为多个进程同时进行。
并行执行:多个任务器执行多个进程,同一时间多个进程在执行。
1.1进程概念
1.程序的一次运行过程称为进程
2.进程是有生命周期的,是一个动态过程,分为创建态、就绪态、运行态、阻塞态、消亡态
3.进程是资源分配的最小单位,系统会给每个进程分配4G的虚拟内存,其中0--3G的用户空间是独立的,3--4G的内核空间时共享的
4.进程是独立的,可以被任务器调度,调度的原则是时间片轮询、上下文切换
1.2进程的内存管理
1> 系统会给每个进程分配4G的虚拟内存
2> 多个进程会独立拥有0--3G的用户空间,用户空间又分为栈区、堆区、静态区
3> 多个进程共享一份内核空间
4> 物理内存:内存条(硬件上)真正存在的存储空间
5> 虚拟内存:程序运行后,有4G的虚拟地址,由物理内存通过内存映射单元映射而来,在需要使用内存的时候,会映射到物理内存上
6> 在32位操作系统上,虚拟内存的空间是4G
在64位系统上,虚拟内存的空间是256T = 2^48
1.3进程和程序的区别
进程:进程是动态的,进程是程序的一次执行过程,有生命周期,进程会为自己分配内存空间,是资源分配的最小单位
程序:程序是静态的,没有所谓的生命周期,它是在磁盘上存放的二进制文件
1.4进程的种类
进程一共分为三类:交互进程、批处理进程、守护进程
交互进程:他是由shell控制,可以直接与用户进行交互,例如文本编辑器
批处理进程:维护了一个队列,被放入队列中的进程会统一进行处理。例如gcc编译器的一步到位的编译
守护进程:脱离终端而存在的进程,随着系统的启动而运行,随着系统的关闭而结束。例如服务进程
1.5进程的PID概念
PID:进程号(process ID)
PPID:父进程号
进程号是进程的唯一标识,他是一个大于等于0的一个整数,并且每个进程的进程号不会重复
每个进程都是继承父进程而得到的,所以每个进程都会有父进程
在linux系统中的根目录下的proc目录中,存放的以数字命名的都是一个进程
1.6特殊的进程
1> 系统启动后,至少要运行三个特殊进程,进程号分别是 0、1、2
2> 0号进程:又称为 idel进程,他是有linux系统启动后的第一个进程,是1号和2号进程的父进程,这个进程也叫空闲进程,当系统中的其他进程都不执行时,运行该进程。
3> 1号进程:称为 init进程,是由0进程产生,完成一些系统启动时的必要初始化工作,也是孤儿进程的父进程,可以完成对孤儿进程的收尸工作
4> 2号进程:称为kthreadd进程,是右0号进程产生,用于调度相关进程,也称调度进程
5> 孤儿进程:当前进程还在运行,但是其父进程已经退出,该进程称为孤儿进程,会被init进程收养
6> 僵尸进程:当前进程已经运行结束,但是其父进程没有为其收尸
1.7有关进程的shell指令
查看进程信息指令:ps
ps -ef : 可以查看进程间的关系
ps -ajx:可以查看进程的状态
ps -aux:可以查看当前进程所占内存和cpu的资源占有率
top指令:动态查看进程相关信息
htop指令:带颜色查看进程相关信息
单独获取进程的进程号:pidof 进程名
向进程发送信号指令:kill指令 (重点)
使用格式:kill -信号号 pid
能够发送的信号,可以通过指令kill -l 查看.
2.进程状态
2.1进程状态的描述
man ps
2.2进程状态的切换
进程主要的状态一共有五种:创建态、就绪态、运行态、阻塞态、死亡态
2.3具体状态转换的实例
运行一个可执行程序,并查看其状态
查看后台运行进程的作业号:jobs
将停止的进程,切换到后台运行:bg 作业号
将后台运行的进程,切换到前台运行:fg 作业号
直接将程序运行于后台:./a.out &
3.多进程编程
3.1创建进程
1.进程创建过程是子进程拷贝父进程的资源,进而产生一个独立的进程个体,子进程会拥有父进程在创建进程之前的所有资源
2.创建进程的api函数 fork
#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
功能:创建出一个子进程
参数:无
返回值:在父进程中,该函数返回子进程的pid号,在子进程中该函数返回0,失败返回-1并置位错误码,并且不会创建出子进程
注意:当子进程创建出来后,父子进程都会执行fork之后的语句
3.不关注返回值的情况时,n个fork会产生2^n个进程,并且多个进程之间没有先后顺序执行
3.2getpid/getppid 进程号的获取
#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void);
功能:获取当前进程的pid号 参数:无 返回值:成功返回当前进程的pid号,不会失败
pid_t getppid(void);
功能:获取当前进程的父进程的pid号 参数:无 返回值:成功返回当前进程的父进程pid号,不会失败
3.3exit/_exit 进程退出函数
#include <stdlib.h>
void exit(int status);
功能:刷新标准io的缓冲区后,退出进程 参数:进程退出时的状态,会将 status&0377的结果返回给父进程 EXIT_SUCCESS(0):表示成功退出 EXIT_FAILURE(1):表示失败退出 返回值:无
#include <unistd.h>
void _exit(int status);
功能:不刷新标准io的缓冲区,直接退出进程 参数:进程退出时的状态,会将 status&0377的结果返回给父进程 EXIT_SUCCESS(0):表示成功退出 EXIT_FAILURE(1):表示失败退出 返回值:无
3.4wait/waitpid 进程资源的回收
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *wstatus);
功能:阻塞等待子进程的结束并回收子进程的资源,如果子进程不退出,则父进程会一直在该函数处阻塞 参数:接受子进程退出时的状态,一般填NULL,表示不接收 返回值:成功返回退出的子进程的pid号,失败返回-1并置位错误码
pid_t waitpid(pid_t pid, int *wstatus, int options);
功能:可以阻塞也可以非阻塞形式回收子进程的资源
参数1:进程号 >0:表示回收特定的子进程的资源(常用) =0:回收当前进程所在进程组中的任意一个子进程 =-1:表示回收任意一个子进程 (常用) <-1:表示回收其他组(组id为pid的绝对值)中的任意一个子进程
参数2:接收子进程退出时的状态,一般填NULL,表示不接收
参数3:是否阻塞的选项 0:表示阻塞 WNOHANG:表示非阻塞回收
返回值:>0:表示成功回收一个子进程,返回该子进程的pid =0:非阻塞回收资源时,没有子进程退出,该函数返回0 =-1:失败返回-1并置位错误码
3.5创建三个进程
三进程拷贝两个文件,第一个 子进程拷贝前半部分,第二个子进程拷贝后半部分