进程调度之linux操作系统的进程与线程基本概念

来源:互联网 发布:海盗战 知乎 编辑:程序博客网 时间:2024/05/29 08:32

进程是具有独立地址空间的;线程没有独立地址空间,一种说法是内核里面只有线程,因为内核的地址空间是共享的(其实操作系统里面很多实现没有非黑即白的概念)。
有两篇文章写得很好
http://blog.csdn.net/u012927281/article/details/51602898
http://www.2ndmoon.net/weblog/?p=603

关于进程的子进程的补充:

parent、sibling、children都是task_struct中的成员,其中parent是task_struct指针,sibling和children都是list_head结构体。
有趣是因为,除了parent比较容易理解之外,另外两个都“不太正常”。
- sibling.next指向进程的下一个兄弟进程的进程描述符sibling成员,若其后没有其他兄弟进程,则指向父进程;而sibling.prev指向进程的上一个兄弟进程,若其之前没有兄弟进程,则指向父进程。
- children.next指向父进程的第一个子进程的sibling成员(而不是children成员!),而children.prev却指向父进程的最后一个子进程的sibling成员。

创建子进程do_fork    =>p = copy_process(clone_flags, stack_start, regs, stack_size, child_tidptr, NULL, trace);        =>p = dup_task_struct(current);            =>ti = alloc_thread_info_node(tsk, node);            =>err = arch_dup_task_struct(tsk, orig);            =>setup_thread_stack(tsk, orig);//8K内核堆栈区        =>sched_fork(p);            =>p->state = TASK_RUNNING;//子进程为就绪态        =>pid = alloc_pid(p->nsproxy->pid_ns);//申请pid            =>pid = kmem_cache_alloc(ns->pid_cachep, GFP_KERNEL);            =>nr = alloc_pidmap(tmp);            =>hlist_add_head_rcu(&upid->pid_chain,                &pid_hash[pid_hashfn(upid->nr, upid->ns)]);        =>retval = copy_thread(clone_flags, stack_start, stack_size, p, regs);    =>wake_up_new_task(p);//将新的子进程加入就绪队列        =>rq = __task_rq_lock(p);        =>activate_task(rq, p, 0);            =>enqueue_task(rq, p, flags);                =>p->sched_class->enqueue_task(rq, p, flags);//进入就绪队列创建内核线程//powerpc的做法kernel_thread    =>mr    r30,r3      /* function *///压栈,系统调用sys_clone    mr  r31,r4      /* argument */    ori r3,r5,CLONE_VM  /* flags */    oris    r3,r3,CLONE_UNTRACED>>16    li  r4,0        /* new sp (unused) */    li  r0,__NR_clone    sc        =>sys_clone            =>do_fork(clone_flags, usp, regs, 0, parent_tidp, child_tidp);//X86的做法kernel_thread    =>regs.orig_ax = -1;    regs.ip = (unsigned long) kernel_thread_helper;    regs.cs = __KERNEL_CS | get_kernel_rpl();    regs.flags = X86_EFLAGS_IF | 0x2;    =>do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);关于switch_toschedule    =>preempt_disable();    =>cpu = smp_processor_id();    rq = cpu_rq(cpu);    =>prev = rq->curr;    =>next = pick_next_task(rq);//按照策略算法选择下一个要切换的进程    =>context_switch(rq, prev, next);//切换        =>switch_to(prev, next, prev);            =>(last) = __switch_to((prev), (next))                =>new_thread = &new->thread;                old_thread = &current->thread;                =>last = _switch(old_thread, new_thread);                    =>stw   r1,KSP(r3)  /* Set old stack pointer */                    =>lwz   r1,KSP(r4)  /* Load new stack pointer */                    =>lwz   r4,_NIP(r1) /* Return to _switch caller in new task */                        =>DEFINE(_NIP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, nip));                            =>#define DEFINE(sym, val) \                                asm volatile("\n->" #sym " %0 " #val : : "i" (val))                            thread_struct {                                ...                                struct pt_regs  *regs;                                  ...                            }                            struct pt_regs {                                ...                                unsigned long nip;                                unsigned long msr;                                ...                            }                    mtlr    r4                    addi    r1,r1,INT_FRAME_SIZE                    blr    =>preempt_enable_no_resched();

copy_thread初始化子进程的内核栈,和新进程的正文段在linux的核心空间,与其它核心进程以及linux内核共享相同的核心正文段。
进程切换只发生在内核态,在执行进程切换之前,用户态进程使用的所有寄存器内容都已经保存在内核态堆栈上,包括用户态进程的SS和ESP寄存器。
Linux系统存在两类用户进程,用户进程和用户线程。严格意义上说,只有拥有了进程描述符,PID,进程正文端,用户进程的数据段和栈段,核心栈段的进程才被称为用户进程,二没有独立数据段和栈段的进程被称为线程。
LINUX系统中,进程和线程都有自己的进程描述符与核心栈段。其中,核心栈段用来支持用户进程或线程在LINUX核心中执行。

关于switch_to,下面这篇文章讲得挺好
linux内核——进程切换宏switch_to
http://www.cnblogs.com/ISeeIC/p/3625556.html

参考如下博客:
task_struct与进程关系
http://blog.csdn.net/seayoungsjtu/article/details/51077840

关于thread_info结构
Linux进程内核栈与thread_info结构详解–Linux进程的管理与调度(九)
http://blog.csdn.net/gatieme/article/details/51577479

linux内核分析笔记—-进程管理
http://www.cnblogs.com/hanyan225/archive/2011/07/09/2101962.html

原创粉丝点击