进程:一个可执行程序跑起来,操作系统就创建一个进程。
PS:
ps:显示当前进程
ps aux:显示当前所有进程
ps aux | less:分页显示所有进程(方便查看)
注:前几个信息是:USER:进程创建用户;PID:身份标识符 ;cpu占用;MEM:内存占用空间......
ps aux | grep test[进程名]:字符筛选显示所有进程(方便查看,这个是筛选test进程[进程名])
注:敲下的命令,在命令的执行过程中,也是一种进程
进程和可执行程序的区别:
二者没有关联,可执行程序是文件,进程会在内存加载数据。因此删除掉文件,进程依旧存在。
进程的管理(操作系统的内核负责):
1.描述进程(PCB进程控制块->就是一个结构体(task_struct))
task_struct是一个很大的结构体,有很多内容。
2.组织进程
双向链表进行组织,每一个结点都是 task_struct。
task_struct含有什么(关键的两个):
- 进程标识符(PID)
- 内存指针:告诉进程代码/数据都在内存的哪个位置
- 进程的状态:
R(ready):就绪状态,进程在就绪队列中,就会处于这种状态。
S(sleep):睡眠状态,暂时还轮不到。
D:深度睡眠状态,密集的进行IO操作的时候经常出现,例如程序崩溃的时候核心转储文件(吐核、临终遗言)会经常出现。
T(stop):暂停,挂起后台
t(trace):跟踪
X:进程已经结束,这个只是在Linux源码中才可以看到,现实中的看不到了
Z:僵尸进程,和父进程子进程这些东西有关联
- 优先级
注:__pid 和 pid_t 和 int 是等价的 ; getpid:获取进程的pid getppid:获取父进程的pid
fork :代码创建子进程
1.返回值:一次调用,有两个返回值;父进程返回子进程的pid;返回0表示子进程;通常需要让父进程的执行不同的逻辑,就可以借助fork的返回值来区分;如果失败返回 < 0 的结果------a)内存不够 b)进程数量太多,达到上限
注:一个父进程有多个子进程,所以要返回子进程pid
2.执行过程
父子进程都跟随fork来执行。
进程的调度:让少量的CPU完成大量的工作------因为cpu少,工作量太多
方式:并行 vs 并发
并行:两个CPU执行两个进程
并发:一个CPU分别执行两个进程
僵尸进程:
成因:子进程结束之后,父进程没有回收子进程的资源,因为父进程可能要查看子进程结束的原因,子进程就要保留相关信息,解决子进程汇报问题。
危害:内存泄露
处理:直接 kill 是杀不掉子进程的,可以 kill 僵尸进程的父进程。更科学的处理是进程等待。
为什么 kill 父进程,子进程就没了?
因为 kill 父进程之后,子进程就成为孤儿进程。孤儿进程就会被我们 1 号进程收养,然后释放。但是孤儿进程和僵尸进程不是一个东西。
孤儿进程
孤儿进程:不是一种进程状态
指的是父进程结束了,但是子进程还在,子进程的父亲就变成1号进程(通用名字:init,所有进程的祖宗)。