进程:程序运行的实例,目的是为了担当分配系统资源(cpu时间、内存)的实体。创建时与父进程相同,接受父进程地址的逻辑拷贝,并从进程创建系统调用的下一条指令开始执行与父进程一样的代码,他们有相同的代码段,但有不同的数据段。
进程描述符
进程状态
state:表示进程的状态,并且一个进程某一时间点只能为一种状态。
可运行状态(task_running):要么在cpu执行,要么准备就绪
可中断的等待状态(task_interruptible):进程被挂起,等待某个条件为真。硬件中断、是否进程等待的系统资源、传递信号都可以是唤醒进程的条件。
不可中断的等待状态(task_uninterruptible):与可中断的等待状态类似,但传递信号不能改变状态,如打开设备文件对设备程序开始探测。
暂停状态(task_stopped):进程的执行被暂停
跟踪状态(task_traced):进程的执行被debugger程序暂停
僵死状态(exit_zombie):进程的执行被终止
僵死撤销状态(exit_dead):进程由系统删除
PID
它用来表示进程(process id),存于进程描述符的pid字段中
进程描述符处理
linux把内核态的进程堆栈和线程描述符(thread_info)存在单独一个未进程分配的存储区。考虑到效率,地址是8k的倍数。内核态的进程访问内核态的数据段
可以很容易的根据esp得到thread_info,13地址清理即可。
进程链表
进程链表把所有的进程描述符链接起来,它的头部是init_task描述符(0进程)。
进程hash表
如果用双链表来查找pid会非常低下,因此使用进程hash表,冲突部分用双链表
如何组织进程
1.处于task_running状态的的队列
2.处于等待(可中断和不可中断)的队列
进程切换
内核有能力挂起cpu正在运行的进程,并恢复挂起以前的进程的行为。
硬件上下文:每个进程由自己的运行空间,但共享cpu的寄存器,因此在恢复之前,将进程的状态信息重新写入到寄存器。
进程创建
写时复制技术:允许父子进程读相同的物理页,只有写一个页面才复制页面(这样才会进行改变)
轻量级进程(clone创建)允许创建进程共享父进程在内核的很多数据结构(页表,即整个用户态地址空间)及打开的文件表及信号处理
vfork系统调用创建进程能共享其父进程的内存地址空间,为了不影响子进程的运行,会阻塞父进程的运行,直到子进程退出或执行新的程序
fork系统调用会返回0(子进程),父进程pid(父进程),-1(失败),使用写时复制技术
撤销进程
如果子进程在退出之前,父进程已经退出了,那么该子进程会成为init进程的子进程,通过wait4()或waitpid()进行撤销。