Linux中的进程管理

来源:互联网 发布:格拉夫红牌伏特加 知乎 编辑:程序博客网 时间:2024/05/21 07:47
Linux操作系统包括三种不同类型的进程
1.交互进程——经常与用户进行交互,需要花很多时间等待键盘鼠标(标准输入设备)的操作,当输入被接收时,必须很唤醒唤醒进程,否则用户认为系统的反应迟钝。典型的交互式进程有,shell终端,文本编辑器,图形应用程序等。
2.批处理进程——这种进程不必与用户进行交互,经常在后台运行,不必很快的响应。比如的编译程序,数据库搜索引擎及科学计算
3.实时进程——这些进程具有很强的调度需要。这样的进程绝对不会被低优先级的进程阻塞,他们应该有一个短的响应时间,跟重要的是这个响应时间应该有很小的变化。典型的实时程序有视频,音频应用程序,物理传感器收集数据的程序

linux进程调度算法中,将进程分为两中类型:I/O消耗性和cpu消耗性。交互性强的需要高优先级,交互性弱的则是低优先级。比如一个文本编辑器和一个编译程序在运行,文本编辑器是一个交互式程序,大部分时间都在等待I/O设备的输入,而编译程序则大部分时间在CPU上处理。为来提高响应速度,I/O消耗性的程序应该具有高优先级,这样才能提高他的交互性

linux系统采用抢占调用方式:当有更紧急的进程到来时,系统将剥夺当前进程的使用处理器去的权利,从而把处理分配给紧急的进程。
linux还采用时间片轮转的调度方式:进程的时间指的是进程在抢占前可以持续运行的时间。对于某个运行的进程,当时间片用完时,系统将停止他的运行,并将处理器分配给其他的进程。进程时间片的长短可根据优先级来独调度,进程不一定要一次运行完所有的时间片,可以在运行中途切换出去。

为了选择一个进程运行,linux调度程序必须考虑每个进程的优先级。有两种优先级:
静态优先级:这种优先级由用户赋给实时进程,范围为1-99,调度程序从不改变他。
动态优先级:这种优先级只应用于普通进程。实质上它是基本时间片(基本优先级)与当前时期内剩余剩余时间片总和,这种优先级只运用于普通的进程

schedule()函数用于实现进程的调度,它的作用是在运行队列链表中找到一个进程,然后把CPU分配给这个进程。每个cpu都有一个运行队列,当Linux内核要寻找一个新的进程在CPU上运行时,必须只考虑处于可运行状态的进程,(即在TASK_RUNNING状态的进程),因为扫描整个进程链表是相当低效的,所以引入了可运行状态进程的双向循环链表,也叫运行队列(runqueue)。该队列通过task_struct结构中的两个指针run_list链表来维持。队列的标志有两个:一个是“空进程”idle_task、一个是队列的长度。


内核为每个进程都分配来一个task_strut数据结构,称为进程控制块PCB(rpocess control block)

在进程控制块中有这样4项一个policy,priorite,counter,rt_priorite
policy(代表该进程的调度策略)
linux下有3中调度策略:
*******************
1.SCHED_FIFO:先进先出的实时调度策略。当调度程序将CPU指定给某个进程时,并将该进程放到运行队列的首位时,除非由更高的优先级进程,否则该进程将一直占用CPU
2.SCHED_RR:循环轮转调度策略。调度程序把CPU指定给某个进程,并将他放到运行队列尾,时间片运行完在选择其他的进程调度。这样保证同优先级公平竞争CPU
3.SCHED_NORMAL:普通的基于时间和等待时间,并动态的调整进程的优先级的一种调度策略。
*********************
priorite(代表进程的基本优先级)(分配给该进程的时间片)
rt_priorite(代表进程的实时优先级)
counter(代表时间片用完之前剩余的cpu时间的节拍)(该进程剩余的时间片)
  首先,linux会根据policy区分实时进程和普通进程,两者的调度策略不是同的,实时进程优先级应该高于普通进程。然后对于同一类型的不同进程,采用不同的标准来进行选择。  
  对于普通进程,linux采用动态优先调度,依据就是进程counter的大小,进程在创建时,优先级priority被赋予一个初值,一般在0-70之间,这个数字同时也是计数器counter的初值。priorite是分配给该进程的时间片,counter该进程剩余的时间片。当进程运行时,counter逐渐减少,当counter为零时对counter进行赋值,当一个普通进程的时间片用完时,并不是立即用priority对counter重新赋值,只用所有处于可运行状态的普通进程时间片都用完后,才用priority对counter赋值,这个普通进程才有再次被调用的机会。这样就相当于优先级在动态的变化。所以称为动态优先调度。
  对于实时进程,linux采用两中调度策略SCHED_FIFO和SCHED_RR。因为实时进程具有一种程度的紧迫性,所以衡量一个实时进程是否运行,linux具有一定的标准。实时进程中的counter只是用来表示该进程的剩余的时间片,并不作为是否值运行的衡量标准,这和普通进程是由区别的,上面我们看到,每个进程都由两个优先级,实时优先级就是来衡该进程的是否值得运行的衡量标准。
进程控制块中有一个进程状态


还有一点linux中某个进程的调度策略,优先级等是可以作为参数由用户自己决定的,具有相当的灵活性

linux定义了6种进程的状态
#define TASK_RUNNING 0 可执行状态(就绪态)
#define TASK_INTERRUPTIBLE(interruptible) 1可中断的睡眠状态(浅度睡眠)
#define TASK_UNINTERRUPTIBLE 2不可中断的睡眠状态,(深度睡眠)
#define TASK_STOPPED 4挂机状态
#define TASK_ZOMBLE  8僵死状态
#define TASK_DEAD 16死亡状态
僵死状态是非常特殊的一种,他已经放弃了机会所有内存的空间,没有任何的可执行代码,也不可以被调度,仅仅在进程列表中保留一个位置,记载该进程的退出状态等信息供其他进程收集,除此之外,僵死进程不在占任何空间。比如进程调用一个exit函数后,进程并不是立即消失,而是留下一个僵死的进程的数据结构。


linux下的与进程的函数有:
创建进程:
#include<sys/types.h>
#include<unistd.h>
pid_t fork();
pid_t vfork();

执行进程
#include<unistd.h>
void execl(const char* pathname, const char* arg, ......);
void execlp(const char* pathname, const char* arg, ......);
void execle(const char* pathname, const char* arg, ...., char* const envp[]);
void execv(const char* pathname, const char* const arg[]);
void execvp(const char* pathname, const char* const arg[]);
void execve(const char* pathname, const char* const arg[],char* const envp[]);

消亡进程
#include<stdlib.h>
void exit(int status);
void _exit(int status);
void abort();

等待进程
#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int* status);
pid_t waitpid(pid_t pid, int* status, int options);
pid_t wait3(int* status, int options, strut rusage* rusage);
pid_t wait4(pid_t pid, int* status, int options, strut rusage* rusage);
pid_t wait(int status);


system函数
#include<stdlib.h>
int system(const char* cmdstring);

相关命令
ps---进程静态列表  -ef列出所有进程 -efH -以乔木状列出所有进程 -aux每个进程的详细信息
top---进程动态列表
kill--结束一个进程 PID -9立即强制结束一个进程
killall---结束多个给进程
halt---关闭系统
reboot--重启系统
0 0
原创粉丝点击