Reputation: 89
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
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