From: http://blog.csdn.net/xinyuan510214/article/details/50516279
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() 清理僵尸子进程
时间: 2024-10-10 10:28:34