进程:进程就是运行中的程序,指一组有序指令 + 数据 + 资源的集合
进程管理的相关命令:
ps:显示进程的信息
kill pid:结束进程 kill -stop pid:挂起进程 kill -9 pid:强制结束进程
jobs:显示后台和挂起的进程任务 &:在后台运行进程
bg: 任务号,将挂起的进程放在后台执行
fg: 任务号,将挂起或后台的进程放到前台执行
cat /proc/pid/maps:查看进程的虚拟空间布局
通过ps -u查看进程的pid,在通过cat /proc/pid/maps查看虚拟空间分布
进程的运行状态
进程在其生命周期存在多个状态:就绪、运行、阻塞等
就绪:所有资源准备完成,等待CPU空闲状态
运行:在CPU真正执行的状态
阻塞:等待某些事件发生,事件未发生前,不被CPU调度的状态
进程的加载过程
操作系统为每一个进程维护一个页表
线性地址转为物理地址详细参考:https://blog.csdn.net/l_nan/article/details/51188290
进程的创建
进程的创建使用的是fork()函数;fork函数的原型为 pid_t fork(void);
在fork时执行的是写时拷贝技术,fork后,父进程只给子进程拷贝了一个PCB,并不会真正的复制空间,只有当任意进程进行修改时,才会将数据所在的页复制出来;
fork出错,返回-1,fork函数调用一次,返回两次,原来的进程(父进程)返回新进程(子进程)的pid,因为父进程不止拥有一个子进程;新进程返回0,因为子进程只有一个父进程,可以通过调用getpid()得到父进程的进程ID;fork之后,父子进程就是两个独立的进程,谁先运行由操作系统决定
fork哪些会被复制?哪些共享?
fork之后,子进程会复制父进程的虚拟地址空间(.data .bss .heap .stack),.text共享,当然还有打开的文件描述符;但由于传统的fork系统调用直接把所有的资源复制给子进程,这种实现过于简单并且效率低下,因为他拷贝的数据也许并不共享,如果此时子进程执行exec函数系统调用,那么拷贝就失去了意义。如下图:
所以引入写时拷贝,fork之后父进程的虚拟地址空间拷贝给子进程,在虚拟地址空间与物理表建立映射过程中使用写时拷贝,使子进程共享父进程的物理空间,当父子进程对其中一个区域进行写入时,子进程复制一个新的物理页表建立映射,是父子进程之间相互独立,同时节省很多物理内存(不同进程拥有自己独立的虚拟空间);
vfork与fork的区别:
vfork函数不创建子进程的虚拟空间,直接共享父进程的虚拟空间,也就间接共享了物理空间,在调用exec或者exit之后父进程才可能被调度