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版本中做了一些改变:

如果进程是RR,把它放到可运行进程结尾,返回。

否则,把它从可运行进程列表移除,放到到期进程列表,这样在其他可运行进程时间片用完之前不会再运行该进程。

从可执行进程列表中找到另一个要执行的进程。

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上,系统要决定每个处理器上要运行那些程序,这里有两项挑战:

调度程序必须想办法充分利用所有的处理器。

切换程序运行的处理器是需要代价的。

进程会继承父进程的处理器亲和性,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密集型循环在一个实时程序中会继续无止境地运行下去,只要没有优先级更高实时进程变成可运行的。因此设计实时程序的时候要谨慎,这类程序至高无上,可用轻易托跨整个系统,下面是一些要决与注意事项:

因为实时进程会好用系统上一切资源,小心不要让系统其他进程等不到处理时间。

循环可能会一直运行到结束。

小心忙碌等待,也就是实时进程等待一个优先级低的进程所占有的资源。

开发一个实时进程的时候,让一个终端保持开启状态,以更高的优先级来运行该实时进程,发生紧急情况终端机依然会有反应,允许你终止失控的实时进程。

使用chrt设置、取得实时属性。

6、资源限制

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

RLIMIT_AS:地址空间上限。

RLIMIT_CORE:core文件大小上限。

RLIMIT_CPU:可耗用CPU时间上限。

RLIMIT_DATA:数据段与堆的上限。

RLIMIT_FSIZE:所能创建文件的大小上限。

RLIMIT_LOCKS:文件锁数目上限。

RLIMIT_MEMLOCK:不具备CAP_SYS_IPC能力的进程最多将多少个字节锁进内存。

RLIMIT_MSGQUEUE:可以在消息队列中分配多少字节。

RLIMIT_NICE:最多可以将自己的友善值调多低。

RLIMIT_NOFILE:文件描述符数目的上限。

RLIMIT_NPROC:用户在系统上能运行进程数目上限。

RLIMIT_RSS:内存中页面的数目的上线。

RLIMIT_RTPRIO:不具备CAP_SYS_NICE能力进程所能请求的实时优先级的上限。

RLIMIT_SIGPENDING:在队列中信号量的上限,Linux特有的限制。

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_yield()函数 高级进程管理相关推荐

  1. Linux系统调用之wait,waitpid函数(进程相关函数)

    前言 如果,想要深入的学习Linux系统调用中的wait,waitpid函数,还是需要去自己阅读Linux系统中的帮助文档. 具体输入命令: man 2 wait/waitpid 即可查阅到完整的资料 ...

  2. 理解进程、通过调用 fork 函数创建进程

    文章目录 1.理解进程 1.1 CPU核的个数与进程数 1.2 进程 ID 2.通过调用 fork 函数创建进程 1.理解进程 进程(Process),其定义如下:"占用内存空间的正在运行的 ...

  3. linux 高级i o函数,高级I/O函数

    对于socket,最基本的输入输出函数就是,read和write.它们最基本,同样功能也是最少的.Unix中有几个函数是read/write的变种,在基本的输入输出功能上,还增加了一些非常使用的功能和 ...

  4. python函数高级话题

    python函数高级话题 python函数高级话题 递归函数 匿名函数:lambda lambda表达式 高阶函数 python 中常见的高阶函数 (1)filter (2)map (3)reduce ...

  5. 【Linux 内核】进程管理 ( 进程状态 | 进程创建 | 进程终止 | 调用 exit 系统调用函数主动退出 | main 函数返回自动退出 | kill 杀死进程 | 执行异常退出 )

    文章目录 一.进程状态 二.进程创建 三.进程终止 ( 调用 exit 系统调用函数主动退出 | main 函数返回自动退出 | kill 杀死进程 | 执行异常退出 ) 一.进程状态 Linux 进 ...

  6. Linux高性能server编程——高级I/O函数

     高级I/O函数 pipe函数 pipe函数用于创建一个管道,实现进程间的通信. #include <unistd.h> int pipe(int pipefd[2]); 通过pipe ...

  7. Linux | 高级I/O函数

    文章目录 创建文件描述符的函数 pipe函数 dup函数.dup2函数 读取或写入数据 readv函数.writev函数 零拷贝 sendfile函数 splice函数 tee函数 进程间通信--共享 ...

  8. linux 笔记--while循环、函数和进程管理

    while:     break:提前退出循环     continue:提前结束循环,而进入下一轮循环     while :: do            ********     done    ...

  9. Linux内核进程管理基本概念-进程、运行队列、等待队列、进程切换、进程调度

    下面简述一些基本概念,以及对内核代码做最初步的了解: 一 Linux内核进程管理基础 Linux 内核使用 task_struct 数据结构来关联所有与进程有关的数据和结构,Linux 内核所有涉及到 ...

最新文章

  1. 打印二叉树和为某一值的路径
  2. python恶搞表情包-哈哈!我用 Python 把你的朋友变成表情包了
  3. python如何爬虫-Python爬虫具体应该怎么使用?
  4. 稀疏编码(Sparse Coding)(二)
  5. linux下git修改密码后无法使用,git push后账号密码输出错误和修改
  6. ddr4 dqs 频率_一张图看懂如何选择DDR4内存的频率和容量
  7. CF1361C. Johnny and Megan‘s Necklace(构造,欧拉回路,传递闭包)
  8. MySQL Innodb存储引擎使用B+树做索引的优点
  9. ESXi日志分析网站第五版v5.4
  10. 恒生电子23届校招内推
  11. C++语法学习笔记十四:派生类-调用顺序-访问等级-函数遮蔽
  12. 邮件群发工具使用说明​
  13. 微软校园招聘面试经历
  14. 线性方程组在计算机方面的应用,在线性方程组的简单应用》(安顺学院数学和计算机科.doc...
  15. E3000Y影像二维扫描枪(配YoKo引擎开发板)的串口调试
  16. linux rtsp 获取摄像头视频流,用RTSP流式网络摄像头
  17. 性能优化-Tomcat调优
  18. Linux下配置网卡信息
  19. 让应用程序禁止Windows屏幕保护
  20. linux多磁盘合并,挂载到相同文件夹

热门文章

  1. 智能传播中的人机融合智能
  2. CTF Crypto 个人初级训练笔记
  3. 乐学python视频资源_铁乐学python_Day40_进程池
  4. mysql 索引都有哪些,mysql索引类型有哪些
  5. 学计算机的整BIM,学习BIM的电脑配置
  6. 网页中onbeforeunload、onpagehide、onunload、onload、onpageshow的正确执行顺序
  7. Android自定义View之实现简单炫酷的球体进度球
  8. 适用于分段LCD液晶屏控制的参考设计
  9. Mac 中查看内存使用情况命令
  10. ffmpeg视频抽帧命令