BFQ & 设置IO优先级

BFQ是Linux的一种IO调度算法,旨在提供高吞吐、低延迟和公平性。它使用预算分配,根据进程消耗资源情况动态调整预算,以适应不同应用需求。BFQ还考虑进程IO优先级,允许通过ionice命令设置。要启用BFQ,需在系统中加载bfq模块,并修改相应设备的调度策略。此外,可以使用ioprio_set系统调用来设置进程或线程的IO优先级。
摘要由CSDN通过智能技术生成

1 介绍

        BFQ,全称 Budget Fair Queuing / 预算公平排队,是Linux基于CFQ的一个“比例共享”的IO调度算法。按照官方的说法,它具有“高吞吐,低延迟以及公平性”的特点。Linux 5.0内核中,CFQ已经被完全删除,取而代之的是诸如BFQ的多队列算法。

        不同于CFQ中的时间片,BFQ使用预算(budget)分配的方式来实现公平:每个进程在一个窗口有预算的sector数量,花完所有sector(或超时)则进程的请求队列被挂起,等候调度。同时budget会不断调整,如果进程花完了budget,下一次的budget会增加;若没花完,则下一次的budget会减少。而budget越小,调度越频繁(时间敏感应用),budget越大,执行时间越长(高吞吐应用),bfq以这种自适应的方式来实现不同进程的需求,实现低延迟和高吞吐。

        此外,BFQ考虑进程的IO优先级,来决定进程在何时能够被调度。BFQ“严格执行优先级,只要存在较高优先级的队列,就不会为低优先级队列提供服务”。可以通过ionice命令设定优先级。

        具体参考:linux/bfq-iosched.rst at master ·torvalds/linux (github.com)

2 进程的IO优先级

 ionice将IO调度分为三大类:

        (1)RT(Real Time):实时调度,不考虑其他进程的IO,立即访问磁盘。

        (2)BE(Best Effort):缺省调度策略,可以指定优先级(0~7),数值越小优先级越高。

        (3)IDLE:空闲调度,当没有其他进程需要IO时,才能进行调度,无优先级可言。

       PS: 此外还有一个(0)none 优先级。未设置优先级时默认为none,其实也就是BE,只是优先级数是通过cpu中的进程优先级自动计算出来的, io_priority = (cpu_nice +20)/5。一般的用户程序,cpu优先级是0(可查看top命令,“NI”项大多为0),因此默认的io优先级为4。

        以上默认IO请求都是同步请求,因为同步IO才是针对进程而言的。

3 使用方式

3.1 更改IO调度策略

注:linux 5.0以上的版本。

        查看当前调度策略,"sda"对应想要修改策略的盘:

~$ cat /sys/block/sda/queue/scheduler
[mq-deadline] none

        此时这里显示并没有bfq,先检测一下你的系统中有没有bfq模块:

~$ sudo modprobe bfq

        没有报错说明是有的,再次查看调度策略,已经有bfq了:

~$ cat /sys/block/sda/queue/scheduler
[mq-deadline] bfq none

        修改为bfq,再次查看:

~$ sudo echo 'bfq'>/sys/block/sda/queue/scheduler
~$ cat /sys/block/sda/queue/scheduler
mq-deadline [bfq] none

        如果要设置bfq随系统启动加载,参考

3.2 BFQ调参

        BFQ具有以下参数,参数列表 。

        例:若要设置low_latency参数为0

~$ echo 0 > /sys/block/sda/queue/iosched/low_latency

3.3 设置IO优先级

        除了使用ionice命令设置优先级外,还可以使用ioprio_set()系统调用设置进程(线程)的IO优先级,Linux手册链接

        可能会出现头文件linux/ioprio.h链接失败的问题,导致宏定义找不到,图方便可以直接把宏定义copy过来。示例代码:

#include <cstdio>
#include <iostream>
//#include <linux/ioprio.h>  /* Definition of IOPRIO_* constants */
#include <sys/syscall.h>     /* Definition of SYS_* constants */
#include <unistd.h>
using namespace std;
​
#define IOPRIO_CLASS_SHIFT  (13)
#define IOPRIO_PRIO_VALUE(class, data)  (((class) << IOPRIO_CLASS_SHIFT) | data)
​
enum {
    IOPRIO_WHO_PROCESS = 1,        // 代表下一个参数为线程号(0代表自身)
    IOPRIO_WHO_PGRP,               // 代表下一个参数为组号(0代表自身所在组)
    IOPRIO_WHO_USER,               // 代表下一个参数为用户ID(..)
};
// 以上宏定义从linux/ioprio.h中复制
​
enum {
    RT = 1,
    BE ,
    IDLE,
};
​
int main(){
    // 获取当前线程优先级
    int prio = syscall(SYS_ioprio_get, IOPRIO_WHO_PROCESS, 0);
    cout << (prio>>IOPRIO_CLASS_SHIFT) << "," << (prio & 0b1111) << endl;
​
    // 设置当前线程IO优先级为7 (BE)
    syscall(SYS_ioprio_set, IOPRIO_WHO_PROCESS, 0, IOPRIO_PRIO_VALUE(BE, 7));
​
    // 设置PID=80的线程IO优先级为IDLE
    syscall(SYS_ioprio_set, IOPRIO_WHO_PROCESS, 80, IOPRIO_PRIO_VALUE(IDLE, 0));
​
    // 设置当前线程所在组的所有线程IO优先级为2(RT)
    syscall(SYS_ioprio_set, IOPRIO_WHO_PGRP, 0, IOPRIO_PRIO_VALUE(RT, 2));
​
    // 设置进程组号为20的所有线程IO优先级为2(BE)
    syscall(SYS_ioprio_set, IOPRIO_WHO_PGRP, 20, IOPRIO_PRIO_VALUE(BE, 2));
​
    prio = syscall(SYS_ioprio_get, IOPRIO_WHO_PROCESS, 0);
    cout << (prio>>IOPRIO_CLASS_SHIFT) << "," <<  (prio & 0b1111) << endl;
​
    return 0;
}

参考:

调整 I/O 性能|系统分析和调优指南|SUSE Linux Enterprise Server 15 SP1

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值