[转]进程创建-终结流程图

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()    清理僵尸子进程

  

 

转载于:https://www.cnblogs.com/hushpa/p/5689098.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值