linux进程、线程及调度算法(三)

  • 作者: 雪山肥鱼
  • 时间:20210523 08:21
  • 目的:进程之间的调度
# 调度
# 吞吐与响应
# I/O消耗型 vs CPU 消耗型
# 调度器:优先级数组和Bitmaps
  ## RT 策略
  ## 100 - 139 普通线程调度
# 普通线程的奖励与惩罚
  ## CFS 公平调度
  ## 优先级相关的系统调用
    ### chrt 与 renice命令

调度

调度策略值得是大家都在ready时,并且CPU已经被调度时,决定谁来运行,谁来被调度。


与在睡眠的进程无关.png

吞吐 与 响应

图片.png
  • 响应
    最小化某个任务的响应时间,哪怕牺牲其他的任务为代价
  • 吞吐
    全局视野,整个系统的workload 被最大优化。解决系统的负载任务,时间都花在了有用功上。

两者之间有一定矛盾。
响应的优化,意味着高优先级会抢占优先级,会花时间在上下文切换,会影响吞吐。
上下文切换的时间是很短的,几微妙就能搞定。上下文切换本身对吞吐并多大影响,重要的是,切换后引起的cpu 的 cache miss.
每次切换APP, 数据都要重新load一次。
Linux 会尽可能的在响应与吞吐之间寻找平衡。比如在编译linux的时候,会让你选择 kernal features -> Preemption model.
抢占模型会影响linux的调度算法。

1. No forced Preemption (Server) -- 服务器追求是同一段时间,能供提供更大的流量,更大的吞吐,并不需要多高的响应
2. Voluntary Kernal Preemption (Desktop) -- 与3 类似,但不能抢内核,只能内核自己放弃CPU
3. Preemptible kernal (Low-Latency Desktop) -- 手机与桌面,需要响应快,连内核都能抢

I/O 消耗型 vs CPU 消耗型

  • I/O消耗型: CPU利用率低, 进程的运行效率主要受限于I/O速度
    CPU 花 1ms 去发送指令,等待dma,花了100ms,这样往复循环。不需要CPU有多强。
    关心的是及时拿到CPU。但是拿的慢,那么反应就慢
    I/O消耗型的调度,是比CPU消耗型多的。
    比如在编安卓,中间点一下鼠标,要优先点击鼠标。
  • CPU消耗型:多数时间花在CPU上面 做 运算
big+Little.png

所以 ARM 的架构都是big+LITTLE, 一个很猛CPU+ 多个 性能较差的 CPU, 那么可以把I/O型任务的调度 放在 LITTLE CPU上。需要计算的放在big上。

调度器: 优先级数组和 Bitmaps

调度器设计.png

早期2.6 内核将优先级划分了 0-139 bit的优先级。数值越低,优先级越高。0-99优先级 都是 RT(即时响应)的 ,100-139都是非RT的,即normal。
调度的时候 看哪个bitmap 中的 优先级上有任务ready。可能多个任务哦。

RT 策略

  • SCHED_FIFO
    不同优先级按照优先级高的跑到睡眠,优先级低的再跑,同等优先级先进先出
  • SCHED_RR(Round Robin)
    不同优先级按照优先级高的先跑到睡眠,优先级低的再跑,同等优先级轮转,你跑一会,我跑一会。
    RT 中RR 和 FIFO也会互相抢占,谁优先级高就可以抢其他的

100-139 普通线程调度

  • nice 调度策略
    100 优先级 对应的 nice值 -20 越靠前,越优先调度,越坏
    139 优先级 对应的 nice 值 19 越靠后,让出优先调度,越nice

在普通优先级线程调度中,高优先级并不代表对低优先级的绝对优势。会在不同优先级进行轮转。
100 就是比101高,101也会比102高,但100 不会堵着101。
众屌丝进程在轮转时,优先级高的:

  • 会占有更多的时间片,大家转的时候,优先级高的会多转一会
  • 从睡眠态醒来,会去抢优先级低的,再去和优先级低的进程一起轮转。
    比喻:
    等级100的屌丝有10块钱,分给101,5快,101 再给102 1块。。。

普通线程的奖励与惩罚

初始设置nice值为0,linux 会探测 你是喜欢睡眠,还是干活。越喜欢睡,linux 越奖励你,优先级上升(nice值减少)。越喜欢干活,优先级下降(nice值增加)。所以一个进程在linux中,干着干着 优先级越低,睡着睡着 优先级越高。

后期linux补丁中

  • /proc/sys/kernel/sched_rt_period_us
  • /proc/sys/kernel/sched_rt_runtime_us
    比如:0 -99 RT 优先级的线程 ,1s内 只能跑0.95秒,剩下的给屌丝进程一点汤喝。

普通线程的改良 :CFS 公平调度

CFS算法.png

红黑树,数据结构, 左边节点小于右边节点
同时兼顾了 CPU/IO 和 nice。
数值代表着 进程运行到目前为止的virtual runtime 时间。

权重计算.png

(pyhsical runtime) / weight * 1024(系数)。
优先调度 节点值(vruntime)最小的线程。权重weight 其实有nice 来控制。

一个线程一旦被调度到,则物理运行时间增加,vruntime增加,往左边走。
weight的增加,也导致vruntime减小,往右边走。
总之 CFS让线程 从左滚到右,从右滚到左。即照顾了I/O(喜欢睡,分子小) 也 照顾了 nice值低(分母高).所以 由喜欢睡,nice值又低的线程,最容易被调度到。
自动调整,无需向nice一样做出奖励惩罚动作,个人理解权重其实相当于nice

但是 此时 来一个 0-99的线程,进行RT调度,都可以瞬间秒杀你!因为人家不是普通的,是RT的!

一个多线程的进程中,每个线程的调度的策略 如 fifo rr normal, 都可以不同。每一个的优先级都可以不一样。
实验举例, 创建2个线程,同时开2个:

#include <stdio.h>
#include <pthread.h>
#include <sys/types.h>

void *thread_fun(void *param)
{
    printf("thread pid:%d, tid:%lu\n", getpid(), pthread_self());
    while (1) ;
    return NULL;
}

int main(void)
{
    pthread_t tid1, tid2;
    int ret;

    printf("main pid:%d, tid:%lu\n", getpid(), pthread_self());

    ret = pthread_create(&tid1, NULL, thread_fun, NULL);
    if (ret == -1) {
        perror("cannot create new thread");
        return 1;
    }

    ret = pthread_create(&tid2, NULL, thread_fun, NULL);
    if (ret == -1) {
        perror("cannot create new thread");
        return 1;
    }

    if (pthread_join(tid1, NULL) != 0) {
        perror("call pthread_join function fail");
        return 1;
    }

    if (pthread_join(tid2, NULL) != 0) {
        perror("call pthread_join function fail");
        return 1;
    }

    return 0;
}

运行2次,创建两个进程
sudo renice -n -5(nice -5级别) -g(global), 会明显看到 一个进程的CPU占用率是另一个的 3倍。

优先级相关的系统调用

system call.png
struct sched_param the_priority;

//设置线程是是 fifo 调度,且优先级是50
the_priority.sched_priorty = 50; //99-50,在 bitmap上应该是49
pthread_setschedparam(pthread_self(), SCHED_FIFO, &the_priority);//看的出以线程为单位

为什么cpu都已经达到200%,为什么系统不觉得卡呢?因为,我们的线程在未设置优先级时,是normal调度模式,且是 CPU消耗型 调度级别其实不高。

chrt 工具的使用

chrt -f -a -p 50 12798

利用chrt工具,可以将进程 调整为 50 从normal的调度策略 升为RT (fifo)级别的调度策略,会出现:

  1. CPU 不升(也没法在升高了)反降。 因为有下面两项针对RT调度级别进程的限制(可修改的)
    /proc/sys/kernel/sched_rt_period_us
    /proc/sys/kernel/sched_rt_runtime_us
  2. 会非常的卡,因为RT 是可以秒杀 CFS,鼠标中断的这种 I/O型也拼不过CPU计算型的进程了。

chrt , nice renice 的调度策略 都是以线程为单位的,以上 设置的将进程下的所有线程进行设置nice值
线程是调度单位,进程不是,进程是资源封装单位!

两个同样死循环的normal优先级线程,其中一个nice值降低,该线程的CPU 利用率就会比另一个CPU的利用率高。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容