下面是完整的 Linux 进程运行流程:
下面是基本的执行流程图:
- arch / x86 / include / asm / unistd_32.h: fork()用户空间来调用(如C程序)--->int $0×80产生0x80软中断--->arch / x86 / kernel / entry_32.S: ENTRY(system_call)中断处理程序system_call()--->执行SAVE_ALL宏保存所有CPU寄存器值--->arch / x86 / kernel / syscall_table_32.S: ENTRY(sys_call_table)系统调用多路分解表--->arch / x86 / kernel / process_32.c: sys_fork()--->kernel / fork.c: do_fork()复制原来的进程成为另一个新的进程--->kernel / fork.c: copy_process()--->struct task_struct * p;定义新的进程描述符(PCB)--->clone_flags标志的合法性检查--->security_task_create()安全性检查 (SELinux机制)--->kernel / fork.c: dup_task_struct()复制进程描述符--->struct thread_info * ti;定义线程信息结构--->alloc_task_struct()为新的PCB分配内存--->kernel / fork.c: arch_dup_task_struct()复制父进程的PCB--->atomic_set( & tsk - >usage, 2)将PCB使用计数器设置为2,表示活动状态--->copy_creds()复制权限及身份信息--->检测进程总数是否超过max_threads--->初始化PCB中各个字段--->sched_fork()调度器相关设置--->复制进程所有信息copy_semundo(),
- copy_files(),
- --->copy_signal(),
- copy_mm()--->copy_thread()复制线程--->alloc_pid()分配pid--->更新属性和进程数量计数--->kernel / sched.c: wake_up_new_task()把进程放到运行队列上,让调度器进行调度--->kernel / sched.c: select_task_rq()选择最佳的CPU(SMP中有多个CPU)--->p - >state = TASK_RUNNING设置成TASK_RUNNING状态--->activate_task()--->enqueue_task()把当前进程插入到对应CPU的runqueue上--->有CLONE_VFORK标志:wait_for_completion()让父进程阻塞,等待子进程结束--->返回分配的pid kernel / sched.c: schedule()调度新创建的进程进程运行中exit()用户空间来调用(如C程序)--->0x80中断跳转到include / linux / syscalls.h: sys_exit()--->kernel / exit.c: do_exit()负责进程的退出--->struct task_struct * tsk = current;获取我的PCB--->set_fs(USER_DS)设置使用的文件系统模式--->exit_signals()清除信号处理函数并设置PF_EXITING标志--->清除进程一系列资源exit_mm(),
- exit_files()--->exit_fs(),
- exit_thread()--->kernel / exit.c: exit_notify()退出通知--->forget_original_parent()把我的所有子进程过继给init进程--->kill_orphaned_pgrp()向进程组内各进程发送挂起信号SIGHUP及SIGCONT--->tsk - >exit_signal = SIGCHLD;向我的父进程发送SIGCHLD信号--->kernel / exit.c: do_notify_parent()通知父进程--->如果父进程处理SIGCHLD信号,返回DEATH_REAP--->如果父进程不处理SIGCHLD信号,返回传入时的信号值--->__wake_up_parent()唤醒父进程--->通知返回DEATH_REAP,设置exit_state为EXIT_DEAD我退出并且死亡--->否则设置我为EXIT_ZOMBIE我退出但没死亡,成为僵尸进程--->如果为DEATH_REAP:release_task()我自己清理相关资源--->如果为僵尸,在我的父进程退出时我会过继给init进程,由init负责清理--->exit_io_context()清理IO上下文--->preempt_disable()禁用抢占--->tsk - >state = TASK_DEAD;设置我为进程死亡状态--->kernel / sched.c: schedule()释放我的PCB,调度另一个新的进程清理僵尸进程:wait系统调用等待子进程结束--->0x80中断最后到达kernel / exit.c: do_wait()--->do_wait_thread()--->wait_consider_task()--->如果子进程为EXIT_DEAD,返回0,wait调用返回,子进程自己清理自己--->如果子进程为EXIT_ZOMBIE:wait_task_zombie()--->xchg()设置僵尸子进程为EXIT_DEAD--->release_task()清理僵尸子进程
来源: http://lib.csdn.net/article/linux/44857