Linux 源码阅读 进程管理
版本:2.6.24
1.准备知识
1.1 Linux系统中,进程是最小的调度单位;
1.2 PCB数据结构:task_struct (Location:linux-2.6.24\include\linux\sched.h)(任务可以和进程混用)
task_struct结构体
2.设计思路图
3.数据结构
4.主要函数
4.1创建进程
1 long do_fork(unsigned long clone_flags, 2 unsigned long stack_start, 3 struct pt_regs *regs, 4 unsigned long stack_size, 5 int __user *parent_tidptr, 6 int __user *child_tidptr) 7 { 8 struct task_struct *p; 9 int trace = 0; 10 long nr; 11 12 if (unlikely(current->ptrace)) { 13 trace = fork_traceflag (clone_flags); 14 if (trace) 15 clone_flags |= CLONE_PTRACE; 16 } 17 18 p = copy_process(clone_flags, stack_start, regs, stack_size, 19 child_tidptr, NULL); 20 /* 21 * Do this prior waking up the new thread - the thread pointer 22 * might get invalid after that point, if the thread exits quickly. 23 */ 24 if (!IS_ERR(p)) { 25 struct completion vfork; 26 27 /* 28 * this is enough to call pid_nr_ns here, but this if 29 * improves optimisation of regular fork() 30 */ 31 nr = (clone_flags & CLONE_NEWPID) ? 32 task_pid_nr_ns(p, current->nsproxy->pid_ns) : 33 task_pid_vnr(p); 34 35 if (clone_flags & CLONE_PARENT_SETTID) 36 put_user(nr, parent_tidptr); 37 38 if (clone_flags & CLONE_VFORK) { 39 p->vfork_done = &vfork; 40 init_completion(&vfork); 41 } 42 43 if ((p->ptrace & PT_PTRACED) || (clone_flags & CLONE_STOPPED)) { 44 /* 45 * We'll start up with an immediate SIGSTOP. 46 */ 47 sigaddset(&p->pending.signal, SIGSTOP); 48 set_tsk_thread_flag(p, TIF_SIGPENDING); 49 } 50 51 if (!(clone_flags & CLONE_STOPPED)) 52 wake_up_new_task(p, clone_flags); 53 else 54 p->state = TASK_STOPPED; 55 56 if (unlikely (trace)) { 57 current->ptrace_message = nr; 58 ptrace_notify ((trace << 8) | SIGTRAP); 59 } 60 61 if (clone_flags & CLONE_VFORK) { 62 freezer_do_not_count(); 63 wait_for_completion(&vfork); 64 freezer_count(); 65 if (unlikely (current->ptrace & PT_TRACE_VFORK_DONE)) { 66 current->ptrace_message = nr; 67 ptrace_notify ((PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP); 68 } 69 } 70 } else { 71 nr = PTR_ERR(p); 72 } 73 return nr; 74 }
1 asmlinkage int sys_vfork(struct pt_regs regs) 2 { 3 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, ®s, 0, NULL, NULL); 4 }
1 asmlinkage int sys_fork(struct pt_regs regs) 2 { 3 return do_fork(SIGCHLD, regs.esp, ®s, 0, NULL, NULL); 4 }
asmlinkage int sys_clone(struct pt_regs regs) { unsigned long clone_flags; unsigned long newsp; int __user *parent_tidptr, *child_tidptr; clone_flags = regs.ebx; newsp = regs.ecx; parent_tidptr = (int __user *)regs.edx; child_tidptr = (int __user *)regs.edi; if (!newsp) newsp = regs.esp; return do_fork(clone_flags, newsp, ®s, 0, parent_tidptr, child_tidptr); }
1 /* 2 * schedule() is the main scheduler function. 3 */ 4 asmlinkage void __sched schedule(void) 5 { 6 struct task_struct *prev, *next; 7 long *switch_count; 8 struct rq *rq; 9 int cpu; 10 11 need_resched: 12 preempt_disable(); 13 cpu = smp_processor_id(); 14 rq = cpu_rq(cpu); 15 rcu_qsctr_inc(cpu); 16 prev = rq->curr; 17 switch_count = &prev->nivcsw; 18 19 release_kernel_lock(prev); 20 need_resched_nonpreemptible: 21 22 schedule_debug(prev); 23 24 /* 25 * Do the rq-clock update outside the rq lock: 26 */ 27 local_irq_disable(); 28 __update_rq_clock(rq); 29 spin_lock(&rq->lock); 30 clear_tsk_need_resched(prev); 31 32 if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) { 33 if (unlikely((prev->state & TASK_INTERRUPTIBLE) && 34 unlikely(signal_pending(prev)))) { 35 prev->state = TASK_RUNNING; 36 } else { 37 deactivate_task(rq, prev, 1); 38 } 39 switch_count = &prev->nvcsw; 40 } 41 42 if (unlikely(!rq->nr_running)) 43 idle_balance(cpu, rq); 44 45 prev->sched_class->put_prev_task(rq, prev); 46 next = pick_next_task(rq, prev); 47 48 sched_info_switch(prev, next); 49 50 if (likely(prev != next)) { 51 rq->nr_switches++; 52 rq->curr = next; 53 ++*switch_count; 54 55 context_switch(rq, prev, next); /* unlocks the rq */ 56 } else 57 spin_unlock_irq(&rq->lock); 58 59 if (unlikely(reacquire_kernel_lock(current) < 0)) { 60 cpu = smp_processor_id(); 61 rq = cpu_rq(cpu); 62 goto need_resched_nonpreemptible; 63 } 64 preempt_enable_no_resched(); 65 if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) 66 goto need_resched; 67 }
4.2进程调度