IO进程线程 (进程)
目录
一、进程
1、概念
1)进程和程序的区别:
2)Linux的调度机制:
3)进程是资源分配的最小单元
2、进程的五态图
3、物理内存\虚拟内存
4、进程的标识符(PID)
5、特殊的进程ID
6、进程的指令
1)查看系统中的每一个进程(ps -ef)
2)查看CPU、内存使用率及状态(ps -aux)
3)打印进程树(pa -ajx)
4)动态查看进程状态(top)
编辑
5)连用指令grep 查看指定进程的PID
1. ps -ef | grep 进程名
2. ps -aux | grep 进程名
3. ps -ajx | grep 进程名
4. top | grep 进程名
6)查看指定进程的PID(pidof)
7)杀死进程(kill)
7、进程的状态
8、进程函数
1)fork(创建子进程)
1. 子进程
2.连续创建子进程
3. 父子进程的执行顺序
2)getpid | getppid(获取进程号)
3)exit | _exit(结束进程)
4)wait | waitpid(接收回收子进程资源)
5)vfork(创建子进程)
9、特殊进程
1)僵尸进程
1.僵尸进程指 子进程退出了,但是父进程没有回收子进程资源
2. 僵尸进程无法通过 kill 杀死,因为他已经是死掉的进程了
3. 僵尸进程是有害的,必须回收,因为僵尸进程会占用PCB和CPU资源
4. 回收僵尸进程
2)孤儿进程
3)守护进程(幽灵进程)
4)创建守护进程
作业:
1. 创建一个进程扇
2. 创建一个进程链
3.解析以下程序
4. 实现文件的拷贝,父进程拷贝前一部分,子进程拷贝后一部分
一、进程
进程是指 软件(程序)执行的过程
单核处理:多进程同时处理,实际上是在多个软件(程序)之间快速的来回切换
多核处理:部分多个软件(程序)同时执行
1、概念
进程:进程是程序执行的过程、是资源和调度的独立单元
常用于多个死循环的程序同时执行
1)进程和程序的区别:
程序:程序是静态的,存储在硬盘上的
进程:进程是动态的、存储在内存上,包括创建、调度、消亡的过程
2)Linux的调度机制:
CPU以ms级别的速度在多个进程间来回切换
3)进程是资源分配的最小单元
2、进程的五态图
创建态:申请资源,例如PCB资源,填充控制和使用信息,把进程插入到就绪队列中,等待CPU资源
就绪态:已经获取到所有除CPU以外的所有资源,等待获取CPU资源
运行态:已经获取到CPU资源
阻塞态:遇到阻塞函数(如输入函数)当阻塞解除后,进就绪态
终止态:等待操作系统做善后处理,清楚PCB数据,释放PCB资源
3、物理内存\虚拟内存
4、进程的标识符(PID)
Windows的PID可以通过可以通过任务管理器查看
Linux的PID则需要通过指令 /proc 查看
PID: 进程号,是进程的标识,进程号和标识符一样,是不可重复的,唯一的
PPID:父进程号,是打开当前进程的父进程的PID
PGID:进程组号
SID: 会话号
每打开一个终端就是打开一个会话;
一个会话包含一个前台进程组,以及多个后台进程组;
一个进程组包含多个进程。
5、特殊的进程ID
0 : indel 进程 引导进程 创建 1号 和 2号 进程
1 : init 进程 初始化数据 收养孤儿进程(没有父进程或失去父进程的进程)
2 : kthread 进程 实现进程之间的调度
6、进程的指令
1)查看系统中的每一个进程(ps -ef)
2)查看CPU、内存使用率及状态(ps -aux)
3)打印进程树(pa -ajx)
4)动态查看进程状态(top)
5)连用指令grep 查看指定进程的PID
用管道符 | ,可以将grep 和上述的四个指令连用,实现指定查找。
1. ps -ef | grep 进程名
例:查找进程 a.out 的进程
2. ps -aux | grep 进程名
例:查找进程 a.out 的CPU使用率
3. ps -ajx | grep 进程名
例:查找有关进程 a.out 的进程树
4. top | grep 进程名
例:动态查看 a.out 的进程状态(每3s更新状态)
6)查看指定进程的PID(pidof)
格式:pidof 进程名例:pidof a.out
7)杀死进程(kill)
kill 可以发送62种信号,其中 1~31 是稳定信号、34~64 是不稳定信号
可以使用指令 kill -l 查看62个信号。
其中常用的信号:
2)SIGINT ----- 进程在终端运行时,使用的ctrl c 停止
9)SIGKILL ---- 结束进程 (立刻结束,不会被阻塞,不会被忽略)
15)SIGTERM --- 结束进程 (使进程善后结束,会被阻塞,会被忽略,但是更安全)
18)SIGCONT --- 继续运行进程
19)SIGSTOP ---- 挂起进程格式:kill -信号编号 进程号(PID) 对单个进程执行killall -信号编号 进程名 对进程名的所有进程执行例:kill -9 123456(进程号(PID)) ---- 关闭 123465 单个进程killall -9 a.out --------------- 关闭 a.out 的所有进程
此外还有关kill的指令:
kill -l 信号编号 ----- 变更信号编号的 信号名称 例:kill -l 11 变更 11 的信号名称
kill -l ----------------------------- 查看可用的信号
kill 进程号(PID) 进程号 进程号 ··· ---- 结束多个进程
7、进程的状态
指令 ps -aux 可以查看进程当前的状态
进程的状态主要有以下几种 可以通过 man ps 查看:
D ------- 不可中断的休眠态
R ------- 正在运行
S ------- 可中断的休眠态
T ------- 停止态,挂起态
t ------- bug调试状态,当gdb调试bug
X ------- 死亡态
Z ------- 僵尸(进程结束,但是资源没有被回收)当进程 为 BSD 格式 或 使用 "stat" 关键字时,可以会额外显示以下字符< ------- 高优先级(对其他用户不友好)
N ------- 低优先级(相对的对其他用户友好)
L ------- 将页面所在内存中
s ------- 会话领导
l ------- 多线程
+ ------- 处于前台进程组,运行在前端
8、进程函数
1)fork(创建子进程)
格式: #include <sys/types.h>#include <unistd.h>pid_t fork(void);
功能:拷贝父进程的资源,创建新进程,返回的进程号是子进程的进程号
返回值:成功: 返回给 父进程 子进程的 PID,返回给 子进程 0失败: 返回-1,跟新errno
1. 子进程
进程是运行在映射的虚拟空间内的,父子进程共用同一个虚拟空间的内核
创建子进程时,会拷贝父进程的所有用户空间(栈、堆、静态)
2.连续创建子进程
总进程数是 2^n 个,子孙进程数是 (2^n) -1
3. 父子进程的执行顺序
父子进程的执行顺序是不确定的,CPU根据事件轮询机制访问
可以通过sleep间接控制执行顺序(不建议:太过影响程序的运行速度)
4. 写实拷贝
创建子进程时会拷贝父进程资源,只进行访问,父子进程会映射到同一片共用物理内存共用。
如果父子进程中的任意一个的数据发生修改,那么父子进程会分别映射到不同的物理内存。
2)getpid | getppid(获取进程号)
格式:#include <sys/types.h>#include <unistd.h>pid_t getpid(void); //获取进程id并返回pid_t getppid(void); //获取父进程id并返回
3)exit | _exit(结束进程)
格式:#include <stdlib.h>void exit(int status);
功能:库函数,退出进程的,刷新缓冲区
参数:int status:退出状态值,把该值返回给父进程默认 EXIT_SUCCESS->0表示正常退出,非0 EXIT_FAILURE=1表示异常1.正常退出子进程exit(EXIT_SUCCESS); exit(0);
2.异常退出exit(EXIT_FAILURE); exit(1); exit(-1);
==========================
格式: #include <unistd.h>void _exit(int status);
功能:系统函数,退出进程的,不可以刷新缓冲区
参数: int status:退出状态值,把该值返回给父进程默认 EXIT_SUCCESS->0表示正常退出,非0 EXIT_FAILURE=1表示异常
--------------------------------
注意:exit _exit的退出状态值返回给父进程
4)wait | waitpid(接收回收子进程资源)
格式:#include <sys/types.h>#include <sys/wait.h>
pid_t wait(int *wstatus);
功能:阻塞函数,在父进程中接收子进程的退出状态值,回收子进程资源
参数:int *wstatus:该指针指向的内存中存储子进程的退出状态值不接收写NULL,不接受子进程的退出状态值
返回值:成功返回接受子进程的进程id失败返-1,跟新errno
==============================
1.可以使用一下的宏函数转换后的退出状态值WEXITSTATUS(wstatus)
#define __WEXITSTATUS(status) (((status) & 0xff00) >> 8)
2.手动转换退出状态值status >>8 &0xff& 0xff 的作用 取出 -----> 需要的 <-----这8位
exit(0)---->00000000 00000000 00000000 00000000 -----> 0000 00001------>256--->1 0000 0000 2------>512-->10 0000 00003------>768-->11 0000 0000
=================================
格式:
pid_t waitpid(pid_t pid, int *wstatus, int options);
功能:接收子进程的退出状态值,回收子进程资源,可以设置非阻塞
参数:pid_t pid:< -1 例如-1234,先取绝对值 1234进程组id,获取当前进程组下的任意子进程-1 回收当前进程下的任意子进程0 回收当前进程组下的任意子进程> 0 例如1234,回收指定进程id为1234的进程int *wstatus:该指针中存储子进程的退出状态值写NULL,不接收子进程的退出状态值int options:0:表示阻塞WNOHANG:设置为非阻塞,如果没有子进程退出,则立刻返回
返回值:如果获取到子进程资源,则返回子进程的PID号如果第三个参数中指定WNOHANG,并且没有接收到子进程的资源,此时返回0失败返回-1,跟新errno
--------------------------------
wait(&wstatus)等价于waitpid(-1, &wstatus, 0);wait函数默认阻塞函数,子进程不退出,则父进程永久阻塞,父进程不可以做自己的事
waitpid可以设置为非阻塞形式,子进程没有退出,直接向下继续运行,有课回收不到子进程
信号接收
5)vfork(创建子进程)
格式:#include <sys/types.h>#include <unistd.h>pid_t vfork(void);
功能:创建子进程的,子进程和父进程共用用户空间,先执行子进程后执行父进程返回值:
返回值:成功在父进程中返回子进程PID,子进程中返回0失败返回-1,跟新errno
9、特殊进程
1)僵尸进程
1.僵尸进程指 子进程退出了,但是父进程没有回收子进程资源
2. 僵尸进程无法通过 kill 杀死,因为他已经是死掉的进程了
3. 僵尸进程是有害的,必须回收,因为僵尸进程会占用PCB和CPU资源
4. 回收僵尸进程
使用wait回收进程:由于wait是阻塞函数,会影响父进程
使用waitpid设置非阻塞模式:会导致可能接收不到资源
因此:
可以信号和 wait | waitpid 配合使用,防止僵尸进程的出现
或者杀死僵尸进程的父进程,进程1会收养孤儿进程,进而回收是孤儿进程的僵尸进程
2)孤儿进程
1. 孤儿进程:父进程结束,子进程没有结束,子进程默认会被1号进程收养
2. 孤儿进程是活的进程,是无害的,可以使用 kill 杀死
3.独立于终端,不可以使用 crlt c 结束进程,要使用 kill 杀死进程
4. 孤儿进程一般用于系统的后台进程
3)守护进程(幽灵进程)
1. 守护进程:例如操作系统的后台进程,随着操作系统的启动(结束)而启动(结束);
2. 运行在后台,不会因为终端(前端)的结束而结束
3. 不会在当前终端打印信息
4. 周期性的执行在死循环中
4)创建守护进程
作业:
1. 创建一个进程扇
2. 创建一个进程链
3.解析以下程序
打印顺序:
process_2
process_1
procsee