Sungju's Slow Life

Personal journal


Meaning of /proc/stat

What are the meanings of each field in /proc/stat file?

Some documents said that each field represented in jiffies, but actually it isn’t. It was true on kernel 2.4, but no more in kernel 2.6. We can easily see the meaning of each field at the kernel source.

http://lxr.linux.no/linux+v2.6.27.10/fs/proc/proc_misc.c

static int show_stat(struct seq_file *p, void *v)
 504{
 505        int i;
 506        unsigned long jif;
 507        cputime64_t user, nice, system, idle, iowait, irq, softirq, steal;
 508        cputime64_t guest;
 509        u64 sum = 0;
 510        struct timespec boottime;
 511        unsigned int *per_irq_sum;
 512
 513        per_irq_sum = kzalloc(sizeof(unsigned int)*NR_IRQS, GFP_KERNEL);
 514        if (!per_irq_sum)
 515                return -ENOMEM;
 516
 517        user = nice = system = idle = iowait =
 518                irq = softirq = steal = cputime64_zero;
 519        guest = cputime64_zero;
 520        getboottime(&boottime);
 521        jif = boottime.tv_sec;
 522
 523        for_each_possible_cpu(i) {
 524                int j;
 525
 526                user = cputime64_add(user, kstat_cpu(i).cpustat.user);
 527                nice = cputime64_add(nice, kstat_cpu(i).cpustat.nice);
 528                system = cputime64_add(system, kstat_cpu(i).cpustat.system);
 529                idle = cputime64_add(idle, kstat_cpu(i).cpustat.idle);
 530                iowait = cputime64_add(iowait, kstat_cpu(i).cpustat.iowait);
 531                irq = cputime64_add(irq, kstat_cpu(i).cpustat.irq);
 532                softirq = cputime64_add(softirq, kstat_cpu(i).cpustat.softirq);
 533                steal = cputime64_add(steal, kstat_cpu(i).cpustat.steal);
 534                guest = cputime64_add(guest, kstat_cpu(i).cpustat.guest);
 535                for (j = 0; j < NR_IRQS; j++) {
 536                        unsigned int temp = kstat_cpu(i).irqs[j];
 537                        sum += temp;
 538                        per_irq_sum[j] += temp;
 539                }
 540                sum += arch_irq_stat_cpu(i);
 541        }
 542        sum += arch_irq_stat();
 543
 544        seq_printf(p, "cpu  %llu %llu %llu %llu %llu %llu %llu %llu %llun",
 545                (unsigned long long)cputime64_to_clock_t(user),
 546                (unsigned long long)cputime64_to_clock_t(nice),
 547                (unsigned long long)cputime64_to_clock_t(system),
 548                (unsigned long long)cputime64_to_clock_t(idle),
 549                (unsigned long long)cputime64_to_clock_t(iowait),
 550                (unsigned long long)cputime64_to_clock_t(irq),
 551                (unsigned long long)cputime64_to_clock_t(softirq),
 552                (unsigned long long)cputime64_to_clock_t(steal),
 553                (unsigned long long)cputime64_to_clock_t(guest));
 554        for_each_online_cpu(i) {
 555
 556                /* Copy values here to work around gcc-2.95.3, gcc-2.96 */
 557                user = kstat_cpu(i).cpustat.user;
 558                nice = kstat_cpu(i).cpustat.nice;
 559                system = kstat_cpu(i).cpustat.system;
 560                idle = kstat_cpu(i).cpustat.idle;
 561                iowait = kstat_cpu(i).cpustat.iowait;
 562                irq = kstat_cpu(i).cpustat.irq;
 563                softirq = kstat_cpu(i).cpustat.softirq;
 564                steal = kstat_cpu(i).cpustat.steal;
 565                guest = kstat_cpu(i).cpustat.guest;
 566                seq_printf(p,
 567                        "cpu%d %llu %llu %llu %llu %llu %llu %llu %llu %llun",
 568                        i,
 569                        (unsigned long long)cputime64_to_clock_t(user),
 570                        (unsigned long long)cputime64_to_clock_t(nice),
 571                        (unsigned long long)cputime64_to_clock_t(system),
 572                        (unsigned long long)cputime64_to_clock_t(idle),
 573                        (unsigned long long)cputime64_to_clock_t(iowait),
 574                        (unsigned long long)cputime64_to_clock_t(irq),
 575                        (unsigned long long)cputime64_to_clock_t(softirq),
 576                        (unsigned long long)cputime64_to_clock_t(steal),
 577                        (unsigned long long)cputime64_to_clock_t(guest));
 578        }
 579        seq_printf(p, "intr %llu", (unsigned long long)sum);
 580
 581        for (i = 0; i < NR_IRQS; i++)
 582                seq_printf(p, " %u", per_irq_sum[i]);
 583
 584        seq_printf(p,
 585                "nctxt %llun"
 586                "btime %lun"
 587                "processes %lun"
 588                "procs_running %lun"
 589                "procs_blocked %lun",
 590                nr_context_switches(),
 591                (unsigned long)jif,
 592                total_forks,
 593                nr_running(),
 594                nr_iowait());
 595
 596        kfree(per_irq_sum);
 597        return 0;
 598}

From line 544 to 553, you can see the meaning of each field.

One little strange part is that the value which is calculated during the timer interrupt is converted to clock_t type using cputime64_to_clock_t() macro.

http://lxr.linux.no/linux+v2.6.27.10/include/asm-generic/cputime.h#L67

/*
  65 * Convert cputime64 to clock.
  66 */
  67#define cputime64_to_clock_t(__ct)      jiffies_64_to_clock_t(__ct)
  68

http://lxr.linux.no/linux+v2.6.27.10/kernel/time.c#L618

 618u64 jiffies_64_to_clock_t(u64 x)
 619{
 620#if (TICK_NSEC % (NSEC_PER_SEC / USER_HZ)) == 0
 621# if HZ  USER_HZ
 624        x = div_u64(x, HZ / USER_HZ);
 625# else
 626        /* Nothing to do */
 627# endif
 628#else
 629        /*
 630         * There are better ways that don't overflow early,
 631         * but even this doesn't overflow in hundreds of years
 632         * in 64 bits, so..
 633         */
 634        x = div_u64(x * TICK_NSEC, (NSEC_PER_SEC / USER_HZ));
 635#endif
 636        return x;
 637}
 638EXPORT_SYMBOL(jiffies_64_to_clock_t);

At the end, the internal jiffies value divided by difference between HZ and USER_HZ. The USER_HZ is 100. If HZ is 1000, internal jiffies value will be divided by 10. It means that we see the same result among 2.4 and 2.6, but it does not mean that those values just come from jiffies.

If we want to see the values in seconds, we can divide the value by CLOCKS_PER_SEC macro which is defined in time.h.



One response to “Meaning of /proc/stat”

  1. solution with correct code i need…i getting error while running code similar to u posted for stat info in LKM….pls help …i need to display the proc/stat information by using externel kernel module ..ours similar to first code u placed……thanks in advance….

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: