Askaredox
Askaredox

Reputation: 89

How to get current CPU usage with Linux Kernel Module?

I'd like to get the current CPU and memory usage using Linux Kernel Module. Memory was pretty easy thanks this documentation, but getting CPU usage from cpuinfo.c is quite a challenge. I've search a lot of docs and I haven't got anything useful.

My code until now

/**
 * @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");

I get from this memory nicely, but both cpu freqs I get 0. Thanks in advance for your help.

Upvotes: 1

Views: 2849

Answers (1)

Marco Bonelli
Marco Bonelli

Reputation: 69276

You should be able to get the current frequency of a given CPU using the cpufreq_get() function. This function directly returns the CPU frequency, so you don't have to worry about manually extracting it from the current cpufreq_policy with different functions.

Alternatively, you can get the last known CPU frequency through cpufreq_quick_get().

Here's a working example using cpufreq_get() for all online CPUs:

// 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");

Result on my machine:

[ 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

Upvotes: 3

Related Questions