织梦CMS - 轻松建站从此开始!

百家乐门,百乐门博彩『全讯网5566001』百家乐现金网,百家乐正网开户,太阳城娱乐网,金沙现金网,永利高正网,全讯网,全讯网新2,皇冠现金网,皇冠网网址,博彩网,博彩通,澳门博彩网 9dym.com

当前位置: 主页 > 金沙现金网 >

ULK进程管理总结, 与学习linux的同路人共勉 - 内核

时间:2012-01-23 19:03来源:未知 作者:admin 点击:
稍有积蓄 进程、轻量级进程(LWP)、线程 进程:程序执行体,有生命期,用来分配资源的实体 线程:分配CPU的实体。用户空间实现,一个线程阻塞,所有都阻塞。内核实现,不会所用

稍有积蓄

进程、轻量级进程(LWP)、线程 进程:程序执行体,有生命期,用来分配资源的实体 线程:分配CPU的实体。  用户空间实现,一个线程阻塞,所有都阻塞。  内核实现,不会所用相关线程都阻塞。用LWP实现,用线程组表示这些线程逻辑上所属的进程。
进程描述符 进程描述符(简称pd, process descriptors),结构体是:task_struct  数据较多,存放在kenerl的动态内存空间。  pd的引用放在thread_info中,   thread_info与内核栈,放在一个8K空间(它的地址8K对齐)。内核程序使用的栈空间很小。   thread_info在底部,内核栈在顶部向下增长。    好处:多CPU时方便,每个CPU根据自己的栈指针就可以找到当前的pd (以后用current表示当前CPU运行的进程描述符)。     esp(内核栈指针)低8位置零,就是thread_info地址。   每进程有自己的thread_info, (分配释放函数: alloc_thread_info, free_thread_info)
描述符的内容  相关的ID (一个4元素数组)   进程ID (PID)    PID按创建顺序连续增长,到最大值后从最小值开始。    0号进程:交换进程(swapper)    有PID可用位图,表示那一个PID可用,至少占一个页。   线程组ID(tgid),用LWP实现多线程支持    多进程时,进程id,就是线程组id, 也就是组长的pid(LWP)。 getpid() 取的是线程组的id(tgid), 也是组长的pid.    单线程时,pid = gid。所以getpid,也是真正的pid.   进程组ID(pgrp)。   回话的ID(session).    组ID,都是组长的PID。FIXME: 但pb也有各组长的PID     线程组长:tgid     进程组长:signal->pgrp ,     会话长:signal->session   管理ID数据结构——哈希表管理 (利用id找到所用相关的pd,方便)。    一个哈希表数组(pid_hash),存放四个哈希表, 每一个表代表一类id (pid, tgid, pgrp, session)    每个哈希表的由数组(索引为哈希值)和二维链表(嵌入到进程描述符内的pids中)实现     第一维链表:哈希冲突链表。     第二维链表:要查找的值相同的链表, 叫per-PID list(同一组的所有线程,同一组的所有进程,同一会话的所有进程);   进程组ID(pgrp), 回话ID(session)在共享信号的数据结构里。因为同一进程内的所有LWP,这两个ID都是一样的

  家族关系:由pd里的链表(下级)和pd指针(上级)实现   关系:    亲生父亲:创建自己的进程,或是托孤进程(创建自己的进程死了)。    父亲:自己死时要发信号告知的。一般是亲生父亲,有时是监控自己的进程 (调用ptrace)    孩子:    兄弟:   监控(自己起的名字,类似于监护。由于管理方式相同,也归为家族关系)    监控的进程列表:ptrace_children    被监控的其他进程:ptrace_list (类似于被监控的兄弟)   在链表里为了管理方便:    最大儿子的兄弟是父亲    最小儿子的弟弟也是父亲 ,足球比分 www.188zqw.com   父亲保管最大儿子,和最小儿子
  进程资源及资源限制:   CPU相关:    占用CPU总时间    用户的最大进程数   内存相关:    进程地址空间    锁住内存大小    进程页数 (只有记录,没有限制)    堆大小,栈大小   资源相关:    文件:     core dump大小     最大文件大小     打开文件个数    进程同步与通信     锁数目,     悬挂信号数据     在消息列队中占的大小   相关数据结构 和 处理流程    pd->sigal->rlim 是一个表示进程资源使用情况以及限制的结构的数组。    表示进程资源使用情况以及限制的结构:包含当前值,最大值两个数值。   只有超级用户才能增大资源限制。   一般用户登陆时:    kernel创建root进程,全讯网推荐伟易博,减少limit,    建一个 shell子进程,继承limit.    把shell进程的用户,改成登陆的那个用户
  进程状态(state)   运行,TASK_RUNNING    组织pd的结构:就绪进程链:     一个CPU一组链表,百家乐投注开户,每个链表表示一种优先级。   阻塞    可中断阻塞,TASK_INTERRUPTIBLE     可被硬件中断,“释放资源”事件,信号唤醒。    不可中断阻塞,TASK_UNINTERRUPTIBLE     可被硬件中断,“释放资源”事件,唤醒。     但不能被信号唤醒。可用于驱动程序中。    组织pb的结构:等待列队: 每一类事件一个列队,用内嵌链表实现(虽然没列出内嵌链表节点)     列队头:      自旋锁:防止有一个主函数和中断函数同时操作列队。     列队节点:      独占标志:表示该进程是否要独占资源 (不再唤醒别的进程)      指向pd的指针      用于唤醒进程的回调函数。(提供进程的执行机会,是否操作等待列队由用户决定)   停止    停止TASK_STOPPED     被信号停止    追踪TASK_TRACED     该进程被一个调试进程监控以后,收到任何一个信号就进入该状态    组织pb的结构:FIXME: 信号的等待列队?   退出    退出_僵尸EXIT_ZOMBIE     进程终止,资源没有被回收(父进程要用,没有调wait系列函数)    退出_死亡EXIT_DEAD     进程终止,资源正在被回收(父进程要用,没有调wait系列函数)。     一旦资源回收完成,进程描述符也就被回收了。     它防止该进程再次被wait.    组织pb的结构:不挂到队列上,只在家族关系中,等待父进程收回资源

进程控制:
阻塞(current阻塞到某个列队上):  基本流程   临时生成一个列队节点,初始化。   改变current的状态,放入节点,挂到列队上。   调度 (=====》至此,阻塞完成。 一旦被别的进程唤醒====》从调度函数中返回)   从等待列队上摘除节点。  变化:   将挂列队、调度、从列队删除三步拆开,便于灵活处理。   可中断的、限时、独占的函数类似。只不过进程状态、调度函数、独占标志不同。   非独占的从列队开始添加,独占的从末尾添加。(但一个列队内既有独占的,又有非独占的等待进程,很少见)
唤醒:  基本流程   唤醒一个进程:调用节点里的回调函数   唤醒的时候从列队开头依次唤醒,直到唤醒一url that high a. www.2233126.com ,only pay独占的后停止。  变化   是否只唤醒可中断的进程. (_interruptible后缀)   唤醒的独占进程的数目(1个,多个(_nr后缀),所有(_all后缀))   唤醒后是否不检查优先级,马上给予CPU (有_sync的不检查优先级)。

进程切换  切换pgd (全局页目录),此章不讨论。  切换内核栈,硬件上下文   硬件上下文,就是CPU的寄存器。    一部分(大多数CPU寄存器(除了通用寄存器))在pd中保存(task_struct->thread, 类型是thread_struct),    一部分(通用寄存器)保存在内核栈中.   原来用硬件指令()保存CPU信息。后来改成软件(一个个MOV指令)    容易控制,可以挑选信息保存,便于优化。不保存的做其他用(如:进程间传递)          far jmp:跳至目标进程的TSSD。而linux是每个CPU一个TSS,不是每进程一个    对于一些寄存器(ds、es)可以检查值。    与用硬件指令保存时间差不多。  switch_to 宏   三个参数:    prev: 要换走的进程,一般是当前进程    next: 要换到的进程。    last: 传出参数。当前进程再次被换到时,最后一个占用CPU的进程。(prev指向的进程 就是 next指向的进程 的last)   步骤:    栈切换, 完成后就是在新进程的上执行了:     保存prev(放在eax)     eflags,ebp入内核栈;     保存并装载新的esp (旧的esp放到prev->thread.esp,新的esp是next->thread.esp)      此时current就是新的esp所指的thread_info内的task指针    设置返回地址:     prev进程以后得到执行时的__switch_to的返回地址: __switch_to后的第一条指令, 放入prev->thread.eip,     准备next进程的从__switch_to返回的地址: next->thread.eip入栈.    调用__switch_to ()函数,该函数动作如下:     更新CPU的相关信息(tss和gdt):      存next->thread.esp0(内核栈低)到本地TSS.esp0中。      所在CPU的全局段表里的TLS段, 设成next进程的.      更新tss的I/O位图.     更新CPU的寄存器(pd->thread (tss) 与 CPU寄存器交换数据):      保存FPU, MMX, XMM寄存器, 先不装载以后需要时通过中断装载(TODO: )      保存prev的fs, gs寄存器. 装载next的      装载next的debug寄存器(debug寄存器一个8个, 进程切换时只需6个)     返回      prev放入eax (prev就是新进程的last)      ret    ret返回的地址: (__switch_to之前被存入栈中, __switch_to ret时进入eip)     如果是next新进程, next->thread.eip是iret_from_fork.     如果next不是新进程:      弹出ebp, elfags      把eax放入last变量 (prev就是next进程的last)
任务状态段(一个存CPU状态的数组,tss_struct init_tss[])    每个CPU用段上的一个元素。(FIXME: 用于:用户模式要进入内核模式时,设置相应寄存器)      TSS上存内核栈地址。CPU上的程序从用户模式转到内核模式,设置esp。      TSS存I/O端口许可位图。用户模式程序用到I/O时,检查有无权限      所以,进程切换时,要保存的寄存器在pd->thread中。        thread_struct不是thread_info。thread_info中只有少量的数据或指针, 用于通过esp快速定位数据    进程切换时,更新TSS上的信息。      CPU控制单元再从TSS上取需要的信息。      即反应了CPU的当前进程情况,又不需要维护所有进程的状态数据。    TSS的描述符在GDT里。      TSSD:任务状态段描述符 (其实应该叫任务状态描述符,每个TSSD,表示一个CPU的状态, FIXME: :具体以源码为准)      CPU原始设计,每个进程一个TSS元素。      linux设计,每个CPU一个TSS元素,全讯网2。      cpu里的tr寄存器,保存着自己的TSSD(即init_ttss[cpu_id]),不用总上gdt里去取。 (责任编辑:admin)
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片