分析linux进程模型

1.进程概念

  进程是一个具有独立功能的程序关于某个数据集合的一次运行活动。它可以申请和拥有系统资源,是一个动态的概念,是一个活动的实体。它不只是程序的代码,还包括当前的活动,通过程序计数器的值和处理寄存器的内容来表示。

2.linux系统简介

  Linux以它的高效性和灵活性著称,Linux模块化的设计结构,使得它既能在价格昂贵的工作站上运行,也能够在廉价的PC机上实现全部的Unix特性,具有多任务、多用户的能力。Linux是在GNU公共许可权限下免费获得的,是一个符合POSIX标准的操作系统。Linux操作系统软件包不仅包括完整的Linux操作系统,而且还包括了文本编辑器、高级语言编译器等应用软件。它还包括带有多个窗口管理器的X-Windows图形用户界面,如同我们使用Windows NT一样,允许我们使用窗口、图标和菜单对系统进行操作。

3.linux如何组织进程

  3.1进程的状态

    进程执行时,它会根据具体情况改变状态。进程状态是调度和对换的依据。

    ①R (TASK_RUNNING):               可执行状态/运行状态

    ②S (TASK_INTERRUPTIBLE):            可中断的睡眠状态

    ③D (TASK_UNINTERRUPTIBLE):         不可中断的睡眠状态

    ⑤T (TASK_STOPPED or TASK_TRACED):      暂停状态或跟踪状态

    ⑥Z (TASK_DEAD - EXIT_ZOMBIE):        退出状态,进程成为僵尸进程

  3.2进程调度信息

    调度程序利用这部分信息决定系统中哪个进程最应该运行。

    need_resched                               调度标志(下一次的调度机会)

    Nice                                       静态优先级(进程的时间片)

    Counter                             动态优先级(剩余的时间片)

    Policy                                     调度策略

    rt_priority                         实时优先级(只对实时进程有意义)

  3.3进程标识符

    用于识别不同的进程,因此就引入了进程的标识符。

    Pid            进程表示符

    Uid、Gid                                用户表示符、组标识符

    Euid、egid        有效用户标识符、有效组标识符

    Suid、sGid        备份用户标识符、备份组标识符

    Fsuid、fsgid       文件系统用户标识符、文件系统组标识符

  3.4进程组织方式

    3.4.1current宏

      当进程在cpu上执行时,内核通过current获得指向进程task_struct的指针

       这是一段与体系结构相关的代码:

       static inline struct task_struct *get_current(void)
          {  struct task_struct *current; __asm__("andl %%esp,%0; ":"=r" (current) : "0" (~8191UL));return current;}

    3.4.2双向循环列表

        每个进程task_struct结构中的prev_task 和next_task 域用来实现这种链表。

      链表的头和尾都为init_task,它对应的是进程0(pid 为0),也就是所谓的空进程,它是所有进程的祖先。

    3.4.3运行队列      

        运行队列当内核要寻找一个新的进程在CPU 上运行时,必须只考虑处于可运行状态的进程(即在TASK_RUNNING 状态的进程),因为扫描整个进程链表是相当低效的,所以引入了可运行状态进程的双向循环链表,也叫运行队列(run queue)。

      该队列通过task_struct 结构中的两个指针run_list 链表来维持。队列的标志有两个:一个是“空进程”idle_task;一个是队列的长度,,也就是系统中处于可运行状态(TASK_RUNNING)的进程数目,用全局整型变量nr_running 表示。

    3.4.4等待队列        

    等待队列进程必须经常等待某些事件的发生,例如,等待一个磁盘操作的终止,等待释放系统资源或等待时间走过固定的间隔。等待队列实现在事件上的条件等待,也就是说,希望等待特定事件的进程把自己放进合适的等待队列,并放弃控制权。因此,等待队列表示一组睡眠的进程,当某一条件变为真时,由内核唤醒它们。等待队列由循环链表实现。

    3.5进程的状态转换图

    

4、进程的调度

  4.1先来先服务调度算法

  先来先服务(FCFS)调度算法是一种最简单的调度算法,该算法既可用于作业调度,也可用于进程调度。当在作业调度中采用该算法时,每次调度都是从后备作业队列中选择一个或多个最先进入该队列的作业,将它们调入内存,为它们分配资源、创建进程,然后放入就绪队列。在进程调度中采用FCFS算法时,则每次调度是从就绪队列中选择一个最先进入该队列的进程,为之分配处理机,使之投入运行。该进程一直运行到完成或发生某事件而阻塞后才放弃处理机。

  4.2.优先级调度算法

   在优先级调度算法中,每个进程都关联一个优先级,内核将CPU分配给最高优先级的进程。具有相同优先级的进程,按照先来先服务的原则进行调度。假设进程的执行时间和优先级如下,并且这些进程同时存在于内存中时,采取基于优先级调度算法要考虑进程饿死的问题,因为高优先级的进程总是会被优先调度,具有低优先级的进程可能永远都不会被内核调度执行。Aging是对于这个问题的一个解决方案,所谓Aging就是指逐渐提高系统中长时间等待的进程的优先级。比如如果优先级的范围从127到0(127表示最低优先级),那么我们可以每15分钟将等待进程的优先级加1。最终经过一段时间,即便是拥有最低优先级127的进程也会变成系统中最高优先级的进程,从而被执行。

  4.3.短进程优先

  最短CPU运行期优先调度算法(SCBF--Shortest CPU Burst First)该算法从就绪队列中选出下一个“CPU执行期最短”的进程,为之分配处理机。最短作业优先调度是优先级调度的特例。在优先级调度中我们根据进程的优先级来进行调度,在最短作业优先调度中我们根据作业的执行时间长短来调度。

  4.4.cfs调度算法

        全公平调度器(CFS)的设计思想是:在一个真实的硬件上模型化一个理想的、精确的多任务CPU。该理想CPU模型运行在100%的负荷、在精确 平等速度下并行运行每个任务,每个任务运行在1/n速度下,即理想CPU有n个任务运行,每个任务的速度为CPU整个负荷的1/n。
       由于真实硬件上,每次只能运行一个任务,这就得引入"虚拟运行时间"(virtual runtime)的概念,虚拟运行时间为一个任务在理想CPU模型上执行的下一个时间片(timeslice)。实际上,一个任务的虚拟运行时间为考虑到运行任务总数的实际运行时间。 

       CFS 背后的主要想法是维护为任务提供处理器时间方面的平衡(公平性)。CFS为了体现的公平表现在2个方面
      (1)进程的运行时间相等

      (2)睡眠的进程进行补偿

 以下为调度类

static const struct sched_class fair_sched_class = {  
    .next           = &idle_sched_class,  
    .enqueue_task       = enqueue_task_fair,  
    .dequeue_task       = dequeue_task_fair,  
    .yield_task     = yield_task_fair,  
  
    .check_preempt_curr = check_preempt_wakeup,  
  
    .pick_next_task     = pick_next_task_fair,  
    .put_prev_task      = put_prev_task_fair,  
  
#ifdef CONFIG_SMP  
    .select_task_rq     = select_task_rq_fair,  
  
    .load_balance       = load_balance_fair,  
    .move_one_task      = move_one_task_fair,  
    .rq_online      = rq_online_fair,  
    .rq_offline     = rq_offline_fair,  
  
    .task_waking        = task_waking_fair,  
#endif  
  
    .set_curr_task          = set_curr_task_fair,  
    .task_tick      = task_tick_fair,  
    .task_fork      = task_fork_fair,  
  
    .prio_changed       = prio_changed_fair,  
    .switched_to        = switched_to_fair,  
  
    .get_rr_interval    = get_rr_interval_fair,  
  
#ifdef CONFIG_FAIR_GROUP_SCHED  
    .task_move_group    = task_move_group_fair,  
#endif  
}; 

 函数描述

enqueue.task: 当某个任务进入可运行状态时,该函数将得到调用。它将调度实体(进程)放入红黑树中,并对nr_running 变量加1。
dequeue.task: 当某个任务退出可运行状态时调用该函数,它将从红黑树中去掉对应的调度实体,并从nr_running 变量中减1。
yield_task: 在compat_yield sysctl 关闭的情况下,该函数实际上执行先出队后入队; 在这种情况下,它将调度实体放在红黑树的最右端。
check.preempt curr: 该函数将检查当前运行的任务是否被抢占。在实际抢占正在运行的任务之前,CFS 调度程序模块将执行公平性测试。这将驱动唤醒式(wakeup) 抢占。pick_next_task: 该函数选择接下来要运行的最合适的进程。
load_balance: 每个调度程序模块实现两个函数,load_balance_start() 和load_balance_next(),使用这两个函数实现一个迭代器,在模块的load balance 例程中调用。内核调度程序使用这种方法实现由调度模块管理的进程的负载平衡。
set_curr_task: 当任务修改其调度类或修改其任务组时,将调用这个函数。
task_ tick: 该函数通常调用自time tick 函数; 它可能引起进程切换。这将驱动运行时(running) 抢占。
task new: 内核调度程序为调度模块提供了管理新任务启动的机会。CFS 调度模块使用它进行组调度,而用于实时任务的调度模块则不会使用这个函数。

5.个人想法

  linux作为开源系统拥有许多优点

    ①开源,可以让大家对系统进行随意开发,设计出自己所需要的系统。

    ②安全,提供大量网络管理软件,网络安全软件

    ③广泛的硬件支持,可以在现如今的主流处理器上完美运行

  然而他没有windous那样拥有友好的图形化界面,对于初学者来说需要多多学习操作命令,所以需要有比较长的学习时间才能够熟悉使用。

    

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

eg:

https://www.aliyun.com/jiaocheng/158665.html

https://blog.csdn.net/fdssdfdsf/article/details/7894211

http://www.cnblogs.com/hanxiaoyu/p/5576277.html    

http://www.cnblogs.com/yangjiannr/p/Linux-jin-cheng-zhuang-tai.html

 

转载于:https://www.cnblogs.com/youyou123/p/youyou123.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值