Как получить текущую загрузку ЦП с помощью модуля ядра Linux?

Я хотел бы получить текущее использование ЦП и памяти с помощью модуля ядра Linux. Память была довольно простой благодаря этой документации, но получить загрузку ЦП от cpuinfo.c довольно сложно. Я искал много документов, и у меня нет ничего полезного.

Мой код до сих пор

/**
 * @file    modulo.c
 * @author  Some College Student
 * @date    2020 Sep
 * @version 0.1
 * @brief   Memory and CPU usage
 *
*/


#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/seq_file.h>
#include <linux/proc_fs.h>
#include <linux/mm.h>
#include <linux/cpufreq.h>

void __attribute__((weak)) arch_report_meminfo(struct seq_file *m){}

static int my_proc_show(struct seq_file *m, void *v){
    struct sysinfo i;
    struct cpufreq_policy *cp;
    unsigned long uc_temp, tc_temp, um_temp, tm_temp;

    si_meminfo(&i); //gets memory info
    um_temp = i.totalram - i.freeram; //used memory
    tm_temp = i.totalram; //total memory

    //cp = cpufreq_cpu_get(0); //returning 0
    //uc_temp = cp->cur - cp->min; //usec cpu freq
    //tc_temp = cp->max - cp->min; //total cpu freq
    uc_temp = 0;
    tc_temp = 0;

    seq_printf(m, "{\n\t\"um_temp\":%lu,\n\t\"tm_temp\":%lu,\n\t\"uc_temp\":%lu,\n\t\"tc_temp\":%lu\n}\n", um_temp, tm_temp, uc_temp, tc_temp); //writing in JSON format in /proc/modulo file

    arch_report_meminfo(m);

    return 0;
}

static int my_proc_open(struct inode *inode, struct file *file){
    return single_open(file, my_proc_show, NULL);
}

static ssize_t my_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *f_pos){
    return 0;
}

static struct file_operations my_fops={
    .owner = THIS_MODULE,
    .open = my_proc_open,
    .release = single_release,
    .read = seq_read,
    .llseek = seq_lseek,
    .write = my_proc_write
};

static int __init modulo_init(void){
    struct proc_dir_entry *entry;
    entry = proc_create("modulo", 0777, NULL, &my_fops);
    if(!entry) {
        return -1;    
    } else {
        printk(KERN_INFO "Start\n");
    }
    return 0;
}

static void __exit modulo_exit(void){
    remove_proc_entry("modulo",NULL);
    printk(KERN_INFO "End\n");
}

module_init(modulo_init);
module_exit(modulo_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Memory and CPU usage");
MODULE_AUTHOR("Some College Student");

Я получаю от этой памяти хорошо, но обе частоты процессора я получаю 0. Заранее спасибо за вашу помощь.


person Askaredox    schedule 28.09.2020    source источник


Ответы (1)


Вы должны иметь возможность получить текущую частоту данного процессора, используя cpufreq_get(). Эта функция напрямую возвращает частоту ЦП, поэтому вам не нужно беспокоиться о том, чтобы вручную извлечь ее из текущего cpufreq_policy с помощью различных функций.

Кроме того, вы можете получить последнюю известную частоту ЦП через cpufreq_quick_get().

Вот рабочий пример использования cpufreq_get() для всех онлайн-процессоров:

// SPDX-License-Identifier: GPL-3.0
#include <linux/kernel.h>  // printk(), pr_*()
#include <linux/module.h>  // THIS_MODULE, MODULE_VERSION, ...
#include <linux/init.h>    // module_{init,exit}()
#include <linux/smp.h>     // get_cpu(), put_cpu()
#include <linux/cpufreq.h> // cpufreq_get()
#include <linux/cpumask.h> // cpumask_{first,next}(), cpu_online_mask

#ifdef pr_fmt
#undef pr_fmt
#endif
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

static int __init modinit(void)
{
        unsigned cpu = cpumask_first(cpu_online_mask);

        while (cpu < nr_cpu_ids) {
                pr_info("CPU: %u, freq: %u kHz\n", cpu, cpufreq_get(cpu));
                cpu = cpumask_next(cpu, cpu_online_mask);
        }

        return 0;
}

static void __exit modexit(void)
{
        // Empty function only to be able to unload the module.
        return;
}

module_init(modinit);
module_exit(modexit);
MODULE_VERSION("0.1");
MODULE_DESCRIPTION("Get CPU frequency for currently online CPUs.");
MODULE_AUTHOR("Marco Bonelli");
MODULE_LICENSE("GPL");

Результат на моей машине:

[ 2168.420286] cpufreq: CPU: 0, freq: 1333000 kHz
[ 2168.420321] cpufreq: CPU: 1, freq: 1200000 kHz
[ 2168.420358] cpufreq: CPU: 2, freq: 1333000 kHz
[ 2168.420364] cpufreq: CPU: 3, freq: 1600000 kHz
[ 2168.420372] cpufreq: CPU: 4, freq: 1333000 kHz
[ 2168.420402] cpufreq: CPU: 5, freq: 2400000 kHz
[ 2168.420442] cpufreq: CPU: 6, freq: 1200000 kHz
[ 2168.420444] cpufreq: CPU: 7, freq: 1200000 kHz
person Marco Bonelli    schedule 29.09.2020
comment
Все еще возвращая мне ноль, единственное, что мне нужно, это то, что я нахожусь в виртуальной машине. - person Askaredox; 30.09.2020
comment
@Askaredox хм, может быть, это ограничение вашей виртуальной машины? О какой виртуальной машине и архитектуре идет речь? А также какая версия ядра? - person Marco Bonelli; 30.09.2020
comment
Это экземпляр AWS EC2, Ubuntu Server 20.04 и ядро ​​Linux 5.4.0-1025-aws. - person Askaredox; 30.09.2020