进程调度与进程管理

进程管理:
1、创建进程:在Linux系统中,全部的进程都是PID为1的init进程的后代。内核在系统启动的最后阶段启动init进程。该进程读取系统的初始化脚本(initscript)并运行其它的相关程序,终于完毕系统启动的整个进程。Linux提供两个函数去处理进程的创建和运行:fork()和exec()。首先,fork()通过拷贝当前进程创建一个子进程。子进程与父进程的差别只在于PID(每一个进程唯一),PPID(父进程的PID)和某些资源和统计量(比如挂起的信号)。exec()函数负责读取可运行文件并将其加载地址空间開始运行。fork()使用写时拷贝(copy-on-write)页实现。内核在fork进程时不复制整个进程地址空间,让父进程和子进程共享同一个拷贝,当须要写入时,数据才会被复制,使各进程拥有自己的拷贝。在页根本不会被写入的情况下(fork()后马上exec()),fork的实际开销仅仅有复制父进程的页表以及给子进程创建唯一的task_struct。创建进程的fork()函数实际上终于是调用clone()函数。创建线程和进程的步骤一样,仅仅是终于传给clone()函数的參数不同。比方,通过一个普通的fork来创建进程,相当于:clone(SIGCHLD, 0);创建一个和父进程共享地址空间,文件系统资源,文件描写叙述符和信号处理程序的进程,即一个线程:clone(CLONE_VM | CLONE_FS | CLONE_FILES |CLONE_SIGHAND, 0)。在内核中创建的内核线程与普通的进程之间还有个主要差别在于:内核线程没有独立的地址空间,它们仅仅能在内核空间执行。
2、Fork和vfork的区别:

  1. fork ():子进程拷贝父进程的数据段,代码段
    vfork ( ):子进程与父进程共享数据段
  2. fork ()父子进程的运行次序不确定
    vfork 保证子进程先执行,在调用exec 或exit 之前与父进程数据是共享的,在它调用exec 或exit 之后父进程才可能被调度执行。
  3. vfork ()保证子进程先执行,在她调用exec 或exit 之后父进程才可能被调度执行。假设在调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁。
    3、进程的终止和孤儿进程
    进程在执行结束,或接受到它既不能处理也不能忽略的信号,或异常时,都会被终结。此时,依靠do_exit()(在kernel/exit.c文件里)把与进程相关联的全部资源都被释放掉(如果进程是这些资源的唯一使用者)。至此,与进程相关的全部资源都被释放掉了。进程不可执行(实际上也没有地址空间让它执行)并处于TASK_ZOMBIE状态。它占用的全部资源就是内核栈、thread_info和task_struct。此时进程存在的唯一目的就是想它的父进程提供信息。在父进程获得已终结的子进程的信息后,或者通知内核它并不关注那些信息后,子进程持有的task_struct等剩余内存才被释放。
    假设父进程在子进程之前退出,必须有机制保证子进程能找到一个新的父类,否则的话这些成为孤儿的进程就会在退出时永远处于僵死状态,白白的耗费内存。解决方法是给子进程在当前线程组内找一个线程作为父亲,假设不行,就让init做它们的父进程。

进程调度*
1、I/O消耗型和处理器消耗型:I/O消耗型进程:大部分时间用来提交I/O请求或是等待I/O请求,常常处于可执行状态,但执行时间短,等待请求过程时处于堵塞状态。如交互式程序。
处理器消耗型进程:时间大都用在执行代码上,除非被抢占否则一直不停的执行。
调度策略要在:进程响应迅速(响应时间短)和最大系统利用率(高吞吐量)之间寻找平衡。 Linux为了保证交互式应用,所以对进程的对应做了优化,更倾向于优先调度I/O消耗型进程。
2、进程优先级: Linux依据以上思想实现了一种基于动态优先级的调度方法。一開始,该方法先设置主要的优先级,然而它同意调度程度依据须要来加、减优先级。比如,假设一个进程在I/O等待上耗费的时间多于其执行时间,那么该进程明显属于I/O消耗型,它的优先级会被动态提高。相反,处理器消耗型进程的优先级会被动态减少。
Linux内核提供两组独立的优先级范围。第一种是nice值,范围从-20到+19,默认值是0。nice值越大优先级越低。另外一种是实时优先级,其值可配置,范围从0到99,不论什么实时进程的优先级都高于普通的进程。
4、时间片:Linux调度程序提高交互程序的优先级,让它们运行得更频繁。于是,调度程序提供了比較长的默认时间片给交互程序。此外,Linux调度程序还能依据进程的优先级动态调整分配给它的时间片。从而保证优先级高的进程,假定也是重要性高的进程,运行的频率高,运行时间长。通过实现这样一种动态调整优先级和时间片长度的机制,Linux调度性性能不但非常稳定并且也非常强健。进程并非一定非要一次就用完它全部的时间片,比如一个拥有100毫秒时间片的进程,能够通过反复调度,分5次每次20毫秒用完这些时间片。当一个进程的时间耗尽时,就觉得到期了。没有时间片的进程不会再投入执行,除非等到其它全部的进程都耗尽了他们的时间片。那个时候,全部进程的时间片会被又一次计算。
5、进程抢占:Linux是抢占式的。当一个进程进入TASK_RUNNING状态,内核会检查它的优先级是否高于当前正在执行的进程。假设是这样,调度程序会被唤醒,抢占当前正在执行的进程并执行新的可执行进程。此外,当一个进程的时间片变为0时,它会被抢占,调度程序被唤醒以选择一个新的进程。

猜你喜欢

转载自blog.csdn.net/weixin_43700671/article/details/88983187