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 }
do_fork()函数(Locatiion:linux-2.6.24\kernel\fork.c)

 

1 asmlinkage int sys_vfork(struct pt_regs regs)
2 {
3     return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, &regs, 0, NULL, NULL);
4 }
vfork()函数(location:linux-2.6.24\arch\x86\kernel\process_32.c)

 

1 asmlinkage int sys_fork(struct pt_regs regs)
2 {
3     return do_fork(SIGCHLD, regs.esp, &regs, 0, NULL, NULL);
4 }
fork()函数(location:linux-2.6.24\arch\x86\kernel\process_32.c)

 

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, &regs, 0, parent_tidptr, child_tidptr);
}
clone()函数(location:linux-2.6.24\arch\x86\kernel\process_32.c)

 

 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 }
schdule()函数(Location:linux-2.6.24\kernel\sched.c

 4.2进程调度