Точный расчет загрузки процессора в Linux с использованием /proc/stat
В / proc / stat есть несколько постов и ссылок о том, как получить загрузку процессора, используя статистику. Тем не менее, большинство из них использует только четыре из 7+ статистических данных о процессоре (user, nice, system и idle), игнорируя оставшиеся значения jiffie CPU, представленные в Linux 2.6 (iowait, irq, softirq).
В качестве примера см. Определение загрузки процессора.
У меня такой вопрос: учитываются ли числа iowait/irq/softirq в одном из первых четырех чисел (user/nice/system/idle)? Другими словами, равняется ли общее количество jiffie сумме первых четырех характеристик? Или же общее количество jiffie равно сумме всех 7 характеристик? Если последнее верно, то формула использования ЦП должна учитывать все числа, например:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
long double a[7],b[7],loadavg;
FILE *fp;
for(;;)
{
fp = fopen("/proc/stat","r");
fscanf(fp,"%*s %Lf %Lf %Lf %Lf",&a[0],&a[1],&a[2],&a[3],&a[4],&a[5],&a[6]);
fclose(fp);
sleep(1);
fp = fopen("/proc/stat","r");
fscanf(fp,"%*s %Lf %Lf %Lf %Lf",&b[0],&b[1],&b[2],&b[3],&b[4],&b[5],&b[6]);
fclose(fp);
loadavg = ((b[0]+b[1]+b[2]+b[4]+b[5]+b[6]) - (a[0]+a[1]+a[2]+a[4]+a[5]+a[6]))
/ ((b[0]+b[1]+b[2]+b[3]+b[4]+b[5]+b[6]) - (a[0]+a[1]+a[2]+a[3]+a[4]+a[5]+a[6]));
printf("The current CPU utilization is : %Lf\n",loadavg);
}
return(0);
}
2 ответа
Я думаю, что iowait/irq/softirq не учитываются ни в одном из первых 4 чисел. Вы можете увидеть комментарий irqtime_account_process_tick в коде ядра для более подробной информации:
(для ядра Linux 4.1.1)
2815 * Tick demultiplexing follows the order
2816 * - pending hardirq update <-- this is irq
2817 * - pending softirq update <-- this is softirq
2818 * - user_time
2819 * - idle_time <-- iowait is included in here, discuss below
2820 * - system time
2821 * - check for guest_time
2822 * - else account as system_time
Для простой обработки см. Функцию account_idle_time:
2772 /*
2773 * Account for idle time.
2774 * @cputime: the cpu time spent in idle wait
2775 */
2776 void account_idle_time(cputime_t cputime)
2777 {
2778 u64 *cpustat = kcpustat_this_cpu->cpustat;
2779 struct rq *rq = this_rq();
2780
2781 if (atomic_read(&rq->nr_iowait) > 0)
2782 cpustat[CPUTIME_IOWAIT] += (__force u64) cputime;
2783 else
2784 cpustat[CPUTIME_IDLE] += (__force u64) cputime;
2785 }
Если процессор находится в режиме ожидания и имеется некоторое ожидание ввода-вывода, он будет считать время в CPUTIME_IOWAIT. В противном случае он считается в CPUTIME_IDLE.
В заключение, я думаю, что jiffies в irq / softirq следует считать "занятым" для процессора, потому что он фактически обрабатывал некоторый IRQ или мягкий IRQ. С другой стороны, jiffies в "iowait" следует считать "простаивающим" для процессора, потому что он ничего не делал, а ожидал ожидающего ввода-вывода.
Из busybox его главное волшебство:
static const char fmt[] ALIGN1 = "cp%*s %llu %llu %llu %llu %llu %llu %llu %llu";
int ret;
if (!fgets(line_buf, LINE_BUF_SIZE, fp) || line_buf[0] != 'c' /* not "cpu" */)
return 0;
ret = sscanf(line_buf, fmt,
&p_jif->usr, &p_jif->nic, &p_jif->sys, &p_jif->idle,
&p_jif->iowait, &p_jif->irq, &p_jif->softirq,
&p_jif->steal);
if (ret >= 4) {
p_jif->total = p_jif->usr + p_jif->nic + p_jif->sys + p_jif->idle
+ p_jif->iowait + p_jif->irq + p_jif->softirq + p_jif->steal;
/* procps 2.x does not count iowait as busy time */
p_jif->busy = p_jif->total - p_jif->idle - p_jif->iowait;
}