`
w2363536460
  • 浏览: 3039 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

linux 进程管理 之 sched_yeild

阅读更多

1、让出处理器

  Linux提供一个系统调用运行进程主动让出执行权:sched_yield。进程运行的好好的,为什么需要这个函数呢?有一种情况是用户空间 线程的锁定。如果一个线程试图取得另一个线程所持有的锁,则新的线程应该让出处理器知道该锁变为可用。用户空间锁没有内核的支持,这是一个最间单、最有效 率的做法。但是现在Linux线程实现引入一个使用futexes的优化解决方案。

  另一个情况是在有处理器密集型程序可用周期性调用sched_yield,试图将该进程对系统的冲击减到最小。不管怎么说,如何调度程序应该是系统的事情,而不是进程自己去管。eg:

int main(){ int ret, i;
    ret = sched_yield(); if(ret == -1){
    printf("调用sched_yield失败!\n");
    } return 0;
}

  那该调用内核是如何实现的?2.6以前的版本sched_yield所造成的影响非常小,如果存在另一个可以运行的进程,内核就切换到该进程, 把进行调用的进程放在可运行进程列表的结尾处。短期内内核会对该进程进行重新调度。这样的话可能出现“乒乓球”现象,也就是两个程序来回运行,直到他们都 运行结束。2.6版本中做了一些改变:

  1. 如果进程是RR,把它放到可运行进程结尾,返回。
  2. 否则,把它从可运行进程列表移除,放到到期进程列表,这样在其他可运行进程时间片用完之前不会再运行该进程。
  3. 从可执行进程列表中找到另一个要执行的进程。

2、进程的优先级

  看过CFS中会看到进程的nice value会决定进程会运行多长时间,或者说是占用的百分比。可以通过系统调用nice来设置、获取进程的nice value。该值的范围是-20~19,越低的值越高的优先级(这个在计算虚拟时间的时候放在分母上),实时进程应该是负数,eg:

int main(){ int ret, i;
    ret = nice(0);
    printf("当前进程的nice value:%d\n", ret);
    ret = nice(10);
    printf("当前进程的nice value:%d\n", ret); return 0;
}

  因为ret本来就可以是-1,那么在判断是否系统调用失败的时候就要综合ret和errno。还有两个系统调用可以更灵活地设 置,getpriority可以获得进程组、用户的任何进程中优先级最高的。setpriority将所指定的所有进程优先级设置为prio,eg:

int main(){ int ret, i;
    ret = getpriority(PRIO_PROCESS, 0);
    printf("nice value:%d\n", ret);
    ret = setpriority(PRIO_PROCESS, 0, 10);
    ret = getpriority(PRIO_PROCESS, 0);
    printf("nice value:%d\n", ret); return 0;
}

  进程有在处理器上执行的优先级,也有传输数据的优先级:I/O优先级。linux有额外的两个系统调用可用显示设置和取得I/O nice value,但是尚未导出:

int ioprio_get(int which, int who); int ioprio_set(int which, int who, int ioprio);

3、处理器亲和性
  Linux支持具有多个处理器的单一系统。在SMP上,系统要决定每个处理器上要运行那些程序,这里有两项挑战:

  1. 调度程序必须想办法充分利用所有的处理器。
  2. 切换程序运行的处理器是需要代价的。

  进程会继承父进程的处理器亲和性,Linux提供两个系统调用用于获取和设定“硬亲和性”。eg:

int main(){ int ret, i;
    cpu_set_t set;

    CPU_ZERO(&set);
    ret = sched_getaffinity(0, sizeof(cpu_set_t), &set); if(ret == -1)
    printf("调用失败!\n"); for(i = 0; i < 10; i++){ int cpu = CPU_ISSET(i, &set);
    printf("cpu=%i is %s\n", i, cpu?"set":"unset");
    }

    CPU_ZERO(&set);
    CPU_SET(0, &set);
    CPU_CLR(1, &set);
    ret = sched_setaffinity(0, sizeof(cpu_set_t), &set); if(ret == -1)
    printf("调用失败!\n"); for(i = 0; i < 10; i++){ int cpu = CPU_ISSET(i, &set);
    printf("cpu=%i is %s\n", i, cpu?"set":"unset");
    } return 0;
}

4、Linux的调度策略与优先级
  关于Linux系统中对进程的几种调度方法和他们的区别就不在这里说了,这里关注的是如何获取、设置这些值。可以使用sched_getscheduler来获取进程的调度策略,eg:

int main(){ int ret, i; struct sched_param sp;
    sp.sched_priority = 1;
    ret = sched_setscheduler(0, SCHED_RR, &sp); if(ret == -1)
    printf("sched_setscheduler failed.\n"); if(errno == EPERM)
    printf("Process don't the ability.\n");

    ret = sched_getscheduler(0); switch(ret){ case SCHED_OTHER:
    printf("Policy is normal.\n"); break; case SCHED_RR:
    printf("Policy is round-robin.\n"); break; case SCHED_FIFO:
    printf("Policy is first-in, first-out.\n"); break; case -1:
    printf("sched_getscheduler failed.\n"); break; default:
    printf("Unknow policy\n");
    } return 0;
}

  sched_getparam和sched_setparam接口可用于取得、设定一个已经设定好的策略,这里不只是返回一个策略的ID,eg:

int main(){ int ret, i; struct sched_param sp;

    sp.sched_priority = 1;
    ret = sched_setparam(0, &sp); if(ret == -1)
    printf("sched_setparam error.\n");

    ret = sched_getparam(0, &sp); if(ret == -1)
    printf("sched_getparam error.\n");

    printf("our priority is %d.\n", sp.sched_priority); return 0;
}

  Linux提供两个用于取得有效优先值的范围的系统调用,分别返回最大值、最小值,eg:

int main(){ int ret, i; struct sched_param sp;

    ret = sched_get_priority_min(SCHED_RR); if(ret == -1)
    printf("sched_get_priority_min error.\n");
    printf("The min nice value is %d.\n", ret);

    ret = sched_get_priority_max(SCHED_RR); if(ret == -1)
    printf("sched_get_priority_max error.\n");
    printf("The mmax nice value is %d.\n", ret); return 0;
}

  关于时间片,这个概念可能在Linux中和传统的在操作系统的课程中学到的还是有很大的区别的,如果感兴趣的化可以看看CFS里面的。通过sched_rr_get_interval可以取到分配给pid的时间片的长度,eg:

int main(){ int ret, i; struct timespec tp;
    ret = sched_rr_get_interval(0, &tp); if(ret == -1)
    printf("sched_rr_get_interval error.\n");
    printf("The time is %ds:%ldns.\n", (int)tp.tv_sec, tp.tv_nsec); return 0;
}

5、实时进程的预防措施
  由于实时进程的本质,开发者在开发和调试此类程序时应该谨慎行事,如果一个实时进程突然发脾气,系统的反应会突然变慢。任何一个CPU密集型循环在一 个实时程序中会继续无止境地运行下去,只要没有优先级更高实时进程变成可运行的。因此设计实时程序的时候要谨慎,这类程序至高无上,可用轻易托跨整个系 统,下面是一些要决与注意事项:

  1. 因为实时进程会好用系统上一切资源,小心不要让系统其他进程等不到处理时间。
  2. 循环可能会一直运行到结束。
  3. 小心忙碌等待,也就是实时进程等待一个优先级低的进程所占有的资源。
  4. 开发一个实时进程的时候,让一个终端保持开启状态,以更高的优先级来运行该实时进程,发生紧急情况终端机依然会有反应,允许你终止失控的实时进程。
  5. 使用chrt设置、取得实时属性。

6、资源限制

  Linux对进程加上了若干资源限制,这些限制是一个进程所能耗用的内核资源的上限。限制的类型如下:

  1. RLIMIT_AS:地址空间上限。
  2. RLIMIT_CORE:core文件大小上限。
  3. RLIMIT_CPU:可耗用CPU时间上限。
  4. RLIMIT_DATA:数据段与堆的上限。
  5. RLIMIT_FSIZE:所能创建文件的大小上限。
  6. RLIMIT_LOCKS:文件锁数目上限。
  7. RLIMIT_MEMLOCK:不具备CAP_SYS_IPC能力的进程最多将多少个字节锁进内存。
  8. RLIMIT_MSGQUEUE:可以在消息队列中分配多少字节。
  9. RLIMIT_NICE:最多可以将自己的友善值调多低。
  10. RLIMIT_NOFILE:文件描述符数目的上限。
  11. RLIMIT_NPROC:用户在系统上能运行进程数目上限。
  12. RLIMIT_RSS:内存中页面的数目的上线。
  13. RLIMIT_RTPRIO:不具备CAP_SYS_NICE能力进程所能请求的实时优先级的上限。
  14. RLIMIT_SIGPENDING:在队列中信号量的上限,Linux特有的限制。
  15. RLIMIT_STACK:堆栈大小的上限。

这些就不多说了,到了实际用到的时候再仔细看,eg:

int main(){ int ret, i; struct rlimit rlim;

    rlim.rlim_cur = 32*1024*1024;
    rlim.rlim_max = RLIM_INFINITY;
    ret = setrlimit(RLIMIT_CORE, &rlim);

    ret = getrlimit(RLIMIT_CORE, &rlim); if(ret == -1)
    printf("getrlimit error.\n");
    printf("RLIMIT_CORE limits: soft=%ld hard=%ld\n", rlim.rlim_cur, rlim.rlim_max); return 0;
}
分享到:
评论

相关推荐

    Linux系统如何构建sched_domain&sched_group hierarchy详解

    Linux 系统中 sched_domain 和 sched_group层次结构的构建详解 在 Linux 系统中,sched_domain 和 sched_group 层次结构是 CPU 调度器的核心组件。sched_domain 代表一个 CPU 的拓扑结构,而 sched_group 则是 ...

    sched_rt.rar_The Real

    一旦一个高优先级的SCHED_FIFO进程开始运行,除非它自愿放弃CPU,否则它会一直运行直到完成或被低优先级的信号中断。 - 进程的优先级是通过静态设置的实时优先级(rt_priority,范围为1到99,数字越大优先级越高)...

    sched_fair.rar_batch_cfs

    在Linux操作系统中,调度器是核心组件之一,它负责决定哪个进程应该获得CPU的执行权。"Sched_fair.rar_batch_cfs" 提到的是完全公平调度器(Completely Fair Scheduler, CFS)中的两类任务调度策略:SCHED_NORMAL 和...

    plugin_sched_switch.rar_The Switch

    在Linux内核调度领域,"plugin_sched_switch.rar_The Switch" 涉及到的是一个核心的机制,即任务切换(Scheduler Switch)。这个压缩包中的`plugin_sched_switch.c` 文件很可能是实现或扩展了内核调度器中关于任务...

    Linux进程调度算法分析

    * Linux2.6.x 内核进程调度算法:设计了全新的数据结构和调度算法,为实时进程(SCHED_FIFO/SCHED_RR)提供 O(1)时间复杂度的调度算法,同时,为了兼顾“完全公平”这一设计思路,设计了 CFS 调度器,为普通进程...

    linux_sched.zip_Linux进程调度

    在Linux操作系统中,进程调度是核心功能之一,它负责决定哪个进程应该获得CPU资源以及运行多长时间。"linux_sched.zip"这个压缩包包含了与Linux进程调度相关的源代码,包括"sched.c"、"main.c"、"exit.c"、"fork.c...

    Linux操作系统进程管理实验

    * int sched_setparam(pid_t pid,const struct sched_param *param):设置一个进程的调度参数,如优先级(sched_param 结构体中的sched_priority 字段)。 * int sched_getparam(pid_t pid,const struct sched_param...

    linux_sched.h.rar_linux

    `linux_sched.h`中定义了各种调度类(scheduler classes),如SCHED_NORMAL、SCHED_FIFO、SCHED_RR等,它们分别对应不同的调度策略,比如普通进程、实时进程等。 在`linux_sched.h`中,`struct task_struct`是核心...

    sched_idletask.rar_class

    这个概念与我们的标题"sched_idletask.rar_class"紧密相关,尽管RAR文件在这里可能是源代码的打包格式,但核心内容涉及到Linux内核的调度机制。 首先,我们需要理解“class”在编程和系统设计中的含义。在C++或类似...

    linux CFS调度以及load balance.pptx

    5. idle_sched_class:用于 idle 进程任务 调度器和调度类的分开设计方便了加入其他类型的调度类。 三、调度策略 Sched Policy 调度策略用于决定进程使用哪种调度类。当前支持的调度策略包括: 1. SCHED_NORMAL ...

    Posix-program-Linux.zip_linux posix_linux program_linux 应用_linux

    7. **线程调度**:了解Linux的调度策略,如SCHED_FIFO、SCHED_RR和SCHED_OTHER等。 8. **线程局部存储**:`pthread_key_create()`和`pthread_getspecific()`等函数实现线程私有数据。 9. **异常处理**:线程的错误...

    linux进程调度

    总而言之,Linux进程调度是操作系统的中心组成部分,它负责管理进程的生命周期,合理分配处理器时间,确保系统的稳定运行。理解和掌握进程调度的工作原理,对于优化系统性能,提高用户满意度都具有重要的意义。

    Linux进程调度策略分析

    - **SCHED_RR**:实时进程按照一定的周期轮流执行,即使当前进程未完成一个时间片的执行,也会被迫让出CPU给下一个相同优先级的实时进程执行。这种方式使得相同优先级的实时进程之间能更加公平地共享CPU资源。 ####...

    Linux 进程管理PPT

    - **用户空间**:包含用户进程本身程序及其数据、进程的堆栈以及系统用于控制和管理进程的信息(如进程控制块)。 - **系统空间**:内核被映射到所有进程中的系统空间。这个空间仅当进程处于核心态时才可访问,...

    LINUX内核的进程调度策略.doc

    调度策略主要包括调度时机、调度方式和调度策略,这三个方面共同构成了Linux内核中复杂的进程管理机制。 首先,调度时机在Linux内核中分为两种类型:自愿调度和非自愿调度。自愿调度是指进程主动通过系统调用如`...

    Linux2.6进程调度机制的剖析.pdf

    SCHED_NORMAL 是普通进程调度策略,SCHED_FIFO 和 SCHED_RR 是实时进程调度策略。 Linux2.6 内核的调度算法是基于进程的动态优先级的,它总是选择当前就绪队列中优先级最高的进程作为候选进程。这种调度算法可以...

    rt.rar_The Real

    - 时间片管理:对于SCHED_RR策略,需要理解时间片的长度是如何影响系统性能的,并可能需要调整`sched_rr_get_interval()`来定制时间片长度。 实时调度策略的选择和配置直接影响到系统的实时性能和稳定性。理解并...

    sched_jobshop.zip_JOBSHOP_cplex_visual c

    标题中的“sched_jobshop.zip_JOBSHOP_cplex_visual c”揭示了这是一个关于调度优化问题的项目,使用了IBM的ILOG CPLEX优化器,并且是用C++编程语言实现的,具有图形化界面。Job Shop问题是一个典型的作业车间调度...

    深入理解Linux内核 第七章进程管理

    ### 深入理解Linux内核之进程管理 #### 一、调度策略介绍 Linux操作系统以其高度可定制性和灵活性著称,在进程管理方面更是如此。本章节主要围绕Linux内核中的进程管理和调度策略进行深入探讨。 **传统的调度算法...

Global site tag (gtag.js) - Google Analytics