From: http://blog.csdn.net/xinyuan510214/article/details/50516279linux
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() 清理殭屍子進程