linux进程管理分析.docx
- 文档编号:2946647
- 上传时间:2022-11-16
- 格式:DOCX
- 页数:52
- 大小:143.52KB
linux进程管理分析.docx
《linux进程管理分析.docx》由会员分享,可在线阅读,更多相关《linux进程管理分析.docx(52页珍藏版)》请在冰豆网上搜索。
linux进程管理分析
Linux
作者:
陈颖
邮箱:
chxxxyg@
博客:
目录
一进程管理原理分析概述1
二进程创建2
1进程管理相关结构2
2进程与线程之间的关系4
3进程创建5
三进程调度14
1进程调度相关结构14
2优先级与负荷权重16
2.1优先级的计算16
2.2负荷权重的计算17
3核心调度器18
3.1周期性调度器18
3.2主调度器19
4完全公平调度类22
4.1数据结构22
4.2完全公平调度类操作方法22
4.2.1虚拟时间计算22
4.2.2延迟计算23
4.2.3完全公平调度类操作方法实现25
4.2.3.1时间更新26
4.2.3.2创建新进程时的处理28
4.2.3.3将进程插入就绪队列29
5实时调度类31
5.1数据结构31
5.2实时调度类32
6负载均衡34
四程序的运行37
1可执行文件37
2程序的运行38
一进程管理原理分析概述
进程创建之后将被插入就绪队列接受调度投入运行,新进程运行之初,它的地址空间与其父进程相同,为运行新的程序它需要调用exec函数将新的可执行程序加载到进程空间,从而运行不同于父进程的程序。
进程创建:
用户空间的进程创建是通过调用系统调用fork、clone、vfork来实现的,对于这些系统调用内核都是通过函数do_fork来处理的,它们的不同在于它们传入的参数clone_flags不一样,它决定了新进程与父进程共享那些资源。
在函数do_fork中,为新进程分配了一个进程描述结构task_struct,并且为新进程分配了两页的栈空间,在栈空间的底部存放着一个thread_info结构,该结构保存了特定于CPU的一些信息。
然后再clone_flags中标志的位共享或是重新分配一些资源,初始化一些调度相关的信息。
最后将新进程插入就绪队列等到调度。
进程调度:
进程可能处于以下几种状态:
运行,等待,睡眠。
运行状态即是此刻正在执行;等待状态就是正出于就绪队列中等待调度;睡眠状态不在就绪队列中,在没被唤醒之前不能得到调度。
就绪队列是管理等待调度进程的结构。
一个CPU只有一个就绪队列rq,然而这个就绪队列并不直接管理进程,它又包含子就绪队列,例如完全公平就绪队列、实时就绪队列。
进程的调度主要基于两个调度器:
周期性调度器和主调度器。
周期性调度器是在内核频率HZ中断中统计一些进程时间信息,并判断进程是否需要调度,如果需要就发起调度请求;主调度器是进程主动放弃CPU控制权,切换到其他进程运行,在住调度器中做了很多进程上下文切换的工作。
上层调度器并不直接对进程进行操作,而是通过进程所属调度类对进城进行操作。
调度类主要有两种:
完全公平调度类、实时调度类。
内核中用0到139来表示进程优先级,0到99供实时进程使用,100到139供普通进程使用,在用户空间对应-20到19的nice值。
完全公平调度类提供类一些方法,这些方法对完全公平队列上的进程进行插入、移除、时间统计等操作。
在完全公平队列上进程是按虚拟时间大小通过红黑树排序的,虚拟时间越小的进程排在红黑树越靠左边,得到运行的可能就越大。
虚拟时间跟进程权重紧密相关,而权重又跟进程优先级相对应。
随着时间的推移,权重越大的进程虚拟时间增加越慢,向右移动的速度就越慢,得到调度的机会就越多,所以优先级越高的进程得到运行的机会就越大。
实时进程类与完全公平调度类大体相同,不同的是在实时就绪队列上,有100个链表头,分别挂接100个不同优先级的实时进程。
选择下一个进程运行时,从小到大扫描链表找出第一个进程运行。
实时进程包含SCHED_RR和SCHED_FIFO,它们在同优先级队列中都是先进先出,不过SCHED_RR有时间片,时间片用完后重新分配时间片将进程放入优先级队列尾,然后就调度其他进程运行。
SCHED_FIFO进程一旦调度运行就可以一直运行下去,除非主动放弃CPU控制权。
在SMP多处理器系统中还要实现负载均衡,将忙碌CPU队列上的进程移动到空闲CPU上。
运行新程序:
新进程运行之初,它的地址空间与其父进程相同,为运行新的程序它需要调用exec函数将新的可执行程序加载到进程空间,从而运行不同于父进程的程序。
二进程创建
1进程管理相关结构
task_struct是一个庞大的结构体,它包含了进程管理的全部信息。
这些信息主要包含以下几个方面:
※状态和执行信息,(如带决信号、使用的二进制格式、进程ID、指向父进程以及其他有关进程的指针、优先级和程序执行有关的时间信息);
※虚拟内存信息;
※用户ID、组ID以及权限;
※进程处理的文件和对应的文件系统信息;
※线程相关的信息;
※进程间通信相关信息;
※进程所用的信号处理程序;
structtask_struct{
volatilelongstate;进程状态
void*stack;指向thread_info结构
atomic_tusage;
unsignedintflags;
unsignedintptrace;进程跟踪相关
......
inton_rq;被插入进程调度队列中时置1
intprio,static_prio,normal_prio;进程优先级、静态优先级、普通优先级
unsignedintrt_priority;事实进程优先级
conststructsched_class*sched_class;指向调度类指针
structsched_entityse;每个普通进程或是调度组都抽象成一个调度实体se
structsched_rt_entityrt;实时进程调度实体
......
unsignedintpolicy;调度策略SCHED_NORMAL、SCHED_RR和SCHED_FIFO等
intnr_cpus_allowed;
cpumask_tcpus_allowed;在多处理器上,用于限制进程可以在哪些CPU上运行
......
structmm_struct*mm,*active_mm;进程虚拟存储空间
......
intexit_state;进程退出状态
intexit_code,exit_signal;进程退出时发送的信号
intpdeath_signal;父进程终止时发送的信号
......
pid_tpid;进程全局ID(对应的有PID命名空间中的局部ID)
pid_ttgid;线程组ID
......
structtask_struct__rcu*real_parent;指向真实的父进程(如果父进程终止了,该进程被寄养到其他进程,它的当前父进程由parent指向)
structtask_struct__rcu*parent;进程退出时信号SIGCHLD所发送的进程。
下面几个字段都成了进程的关系图
structlist_headchildren;本进程的所有子进程
structlist_headsibling;兄弟进程
structtask_struct*group_leader;指向进程组的组长进程
......
这个task_struct可能是一个普通进程,也可能是个组长进程或是会话首进程。
structpid_linkpids[PIDTYPE_MAX];
structlist_headthread_group;
structcompletion*vfork_done;在有vfork创建进程时该完成量保证了子进程先运行
......
unsignedlongnvcsw,nivcsw;自愿/非自愿上下文切换计数
structtimespecstart_time;进程创建时间
structtimespecreal_start_time;/*bootbasedtime*/
......
conststructcred__rcu*real_cred;进程权能相关
conststructcred__rcu*cred;
charcomm[TASK_COMM_LEN];可执行文件名
......
structthread_structthread;处理器特有数据
structfs_struct*fs;文件系统信息
structfiles_struct*files;打开的文件信息
structnsproxy*nsproxy;命名空间
structsignal_struct*signal;进程信号描述符
structsighand_struct*sighand;进程信号处理函数
sigset_tblocked,real_blocked;被阻塞信号的掩码,real_blocked表示临时掩码
sigset_tsaved_sigmask;/*restoredifset_restore_sigmask()wasused*/
structsigpendingpending;存放挂起信号
......
};
无论是进程还是线程它们都有一个task_struct结构和1页或2页的栈空间,在栈空间的底部有一个结构体thread_info,叫做线程描述符,其各成员含义说明如下:
structthread_info{
unsignedlongflags;
intpreempt_count;为0的时候内核可执行抢占否则不能
mm_segment_taddr_limit;指定了进程可以使用的虚拟地址的上限
structtask_struct*task;指向进程的task_struct结构
structexec_domain*exec_domain;执行域,用于在一种计算机上实现多种ABI
......
};
进程描述符,堆栈和线程描述符的关系图如下:
2进程与线程之间的关系
进程和线程的区别就是进程有用户空间而线程没有,但是站在内核角度来看它们都是一样的。
多线程的实现其实就是将多个进程关联起来,让它们共享同一内存地址空间,同一打开文件描述符集等。
这些关联起来的线程就构成了线程组,在线程组内,每个线程都使用此线程组内第一个线程(threadgroupleader)的pid,并将此值存入tgid,当我们使用getpid()函数得到进程ID时,其实操作系统返回的是task_struct的tgid字段。
线程有分为用户线程和内核线程:
用户线程是通过系统调用clone创建的。
他指定了几个标志,CLONE_PARENT_SETTID将生成线程的PID复制到clone调用指定的用户控件中的某个地址parent_tidptr,CLONE_CHILD_SETTID首先会将另一个传递到clone的用户空间指针child_tidptr保存在新进程的task_struct中,在新进程执行时内核会调用函数schedule_tail将当前PID复制到该地址。
上面两个标志对应这两个用户空间的指针,这两个指针指向的地址都用来保存新进程的PID。
它们的不同之处在于前一个指向父进程用户空间,后一个指向子进程用户空间。
这样就将pid同时传入了父进程和子进程的用户空间。
3进程创建
系统调用fork、clone
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- linux 进程 管理 分析