基于Linux的进程分析

什么是进程?

进程是程序执行的实例,是有限状态机的一次迁移过程。进程和程序的区别:动态与静止;多对一。

windows10的相关进程

在Linux中用ps-a列出所有运行中/激活进程

在Linux中使用top命令,可以监视不同进程所使用的资源。(包括:PID,优先级,%CPU,%memory等)

进程运行流程:

 

进程的创建

用户空间内可以通过执行一个程序、或者在程序内调用fork(或exec)系统调用来创建进程,fork调用会导致创建一个子进程,而exec调用则会用新程序代替当前进程上下文。一个新进程的诞生还可以分别通过vfork()和clone()。fork、vfork和clone三个用户态函数均由libc库提供,它们分别会调用Linux内核提供的同名系统调用fork,vfork和clone。下面以fork系统调用为例来介绍。

最终都是直接调用do_fork。进程创建的函数层次结构如下图:

 从图中可以看到 do_fork 是进程创建的基础。可以在 ./linux/kernel/fork.c 内找到 do_fork 函数(以及合作函数 copy_process)。

代码如下:

 

(1)在system_call函数执行之前,CPU控制单元已经将eflags、cs、eip、ss和esp寄存器的值自动保存到该进程对应的内核栈中。随之,在 system_call内部首先将存储在eax寄存器中的系统调用号压入栈中。接着执行SAVE_ALL宏。该宏在栈中保存接下来的系统调用可能要用到的所有CPU寄存器。
    (2)通过GET_THREAD_INFO宏获得当前进程的thread_inof结构的地址;再检测当前进程是否被其他进程所跟踪(例如调试一个程序时,被调试的程序就处于被跟踪状态),也就是thread_info结构中flag字段的_TIF_ALLWORK_MASK被置1。如果发生被跟踪的情况则转向syscall_trace_entry标记的处理命令处。
    (3)对用户态进程传递过来的系统调用号的合法性进行检查。如果不合法则跳入到syscall_badsys标记的命令处。
    (4)如果系统调用好合法,则根据系统调用号查找./linux/arch/x86/kernel/syscall_table_32.S中的系统调用表sys_call_table,找到相应的函数入口点,跳入sys_fork这个服务例程当中。由于 sys_call_table表的表项占4字节,因此获得服务例程指针的具体方法是将由eax保存的系统调用号乘以4再与sys_call_table表的基址相加。syscall_table_32.S中的代码如下:

 

进程调度:

创建好的进程最后被插入到运行队列中,它会通过 Linux 调度程序来调度。Linux调度程序维护了针对每个优先级别的一组列表,其中保存了 task_struct 引用。当正在运行的进程时间片用完时,时钟tick产生中断,调用kernel/sched.c:scheduler_tick()进程调度器的中断处理,中断返回后就会调用schedule()。运行队列中的任务通过 schedule 函数(在./linux/kernel/sched.c 内)来调用,它根据加载及进程执行历史决定最佳进程。

进程销毁:

 进程状态:

R运行状态(running):表明进程要么在运行中,要么在运行队列里面

S睡眠状态(sleeping):意味着进程在等待事件的完成,这个睡眠也叫做可中断睡眠

D磁盘休眠状态(Disk sleep):这个状态的睡眠通常在等待I/O的结束,也叫做不可中断睡眠

T停止状态(stopped):可以发送SIGSTOP信号给进程,让进程停止。也可以发送SIGCONT信号让进程继续运行。

X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里面看到这个状态

Z僵尸状态(zombie):子进程退出,父进程没有读取子进程的退出码,子进程进入Z状态

Linux 还在不断演进,其中一个有待进一步创新和优化的领域就是进程管理。在坚持 UNIX 原理的同时,Linux 也在不断突破。新的处理器架构、对称多处理(SMP)以及虚拟化都将促使在内核领域内取得新进展。其中的一个例子就是 Linux 版本 2.6 中引入的新的 O(1) 调度程序,它为具有大量任务的系统提供了可伸缩性。

 

posted @ 2018-04-28 20:49  晴空~佐罗  阅读(1394)  评论(0编辑  收藏  举报