В ходе поиска я понял, что данные, которые я ищу, хранится в массиве avenrun в течение 1 минуты, 5 минут и 15 минут.
команда top показывает среднюю загрузку всей системы, я пытаюсь программно вычислить загрузка определенного процесса/PID, как показано вверху?
Ниже приведен пример кода, который я написал, и я признаюсь, что некоторая его часть представляет собой просто объединение кода из кода ядра Linux,
p>
Код: Выделить всё
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// Use the kernel's exported avenrun array
extern unsigned long avenrun[];
static struct timer_list load_timer;
#define FSHIFT 11
#define FIXED_1 (1 > FSHIFT;
}
static void update_load_avg(struct timer_list *t)
{
struct task_struct *p;
int nr_running = 0;
unsigned long active, sample_window;
long delta;
rcu_read_lock();
for_each_process(p) {
if (p->state == TASK_RUNNING || p->state == TASK_UNINTERRUPTIBLE)
nr_running++;
}
rcu_read_unlock();
active = nr_running * FIXED_1;
atomic_long_set(&calc_load_tasks, nr_running);
sample_window = READ_ONCE(calc_load_update);
if (time_before(jiffies, sample_window + 10)) {
mod_timer(&load_timer, jiffies + LOAD_FREQ);
return;
}
delta = 0; // Simplified: In actual kernel, it includes NO_HZ delta calculations
if (delta)
atomic_long_add(delta, &calc_load_tasks);
active = atomic_long_read(&calc_load_tasks);
active = active > 0 ? active * FIXED_1 : 0;
// Use kernel's avenrun array
avenrun[0] = calc_load(avenrun[0], EXP_1, active);
avenrun[1] = calc_load(avenrun[1], EXP_5, active);
avenrun[2] = calc_load(avenrun[2], EXP_15, active);
printk(KERN_INFO "Load Average: %lu.%02lu, %lu.%02lu, %lu.%02lu\n",
avenrun[0] >> FSHIFT, (avenrun[0] & (FIXED_1 - 1)) * 100 / FIXED_1,
avenrun[1] >> FSHIFT, (avenrun[1] & (FIXED_1 - 1)) * 100 / FIXED_1,
avenrun[2] >> FSHIFT, (avenrun[2] & (FIXED_1 - 1)) * 100 / FIXED_1);
WRITE_ONCE(calc_load_update, sample_window + LOAD_FREQ);
mod_timer(&load_timer, jiffies + LOAD_FREQ);
}
static int proc_loadavg_show(struct seq_file *m, void *v)
{
// Use kernel's avenrun array
seq_printf(m, "Load Average: %lu.%02lu, %lu.%02lu, %lu.%02lu\n",
avenrun[0] >> FSHIFT, (avenrun[0] & (FIXED_1 - 1)) * 100 / FIXED_1,
avenrun[1] >> FSHIFT, (avenrun[1] & (FIXED_1 - 1)) * 100 / FIXED_1,
avenrun[2] >> FSHIFT, (avenrun[2] & (FIXED_1 - 1)) * 100 / FIXED_1);
return 0;
}
static int proc_loadavg_open(struct inode *inode, struct file *file)
{
return single_open(file, proc_loadavg_show, NULL);
}
static const struct proc_ops proc_loadavg_ops = {
.proc_open = proc_loadavg_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
static int __init loadavg_init(void)
{
proc_create("my_loadavg", 0, NULL, &proc_loadavg_ops);
timer_setup(&load_timer, update_load_avg, 0);
calc_load_update = jiffies;
mod_timer(&load_timer, jiffies + LOAD_FREQ);
return 0;
}
static void __exit loadavg_exit(void)
{
del_timer_sync(&load_timer);
remove_proc_entry("my_loadavg", NULL);
}
module_init(loadavg_init);
module_exit(loadavg_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("jshish");
MODULE_DESCRIPTION("A module to calculate load average similar to /proc/loadavg");
Я начал отлаживать код и понял, что способ расчета nr_running неверен,
Код: Выделить всё
rcu_read_lock();
for_each_process(p) {
if (p->state == TASK_RUNNING || p->state == TASK_UNINTERRUPTIBLE)
nr_running++;
}
rcu_read_unlock();
active = nr_running * FIXED_1;
atomic_long_set(&calc_load_tasks, nr_running);

Кроме того, использование cpu_rq даст мне только нагрузку на основе процессора, я полагаю, что это не зависит от PID:/
Код: Выделить всё
for_each_online_cpu(cpu) {
nr_running += cpu_rq(cpu)->nr_running;
}
active = nr_running * FIXED_1;
atomic_long_set(&calc_load_tasks, nr_running);
Я постарался объяснить как можно больше и предоставил материал, который я пробовал. Пожалуйста, дайте мне знать, если я что-то пропустил в вопросе, и я это исправлю.
Спасибо
Подробнее здесь: https://stackoverflow.com/questions/787 ... ic-process