1

I am using C file IO to read value from a sysfs interface in linux. Path and sample value of the register is as follows:

cat /sys/class/powercap/intel-rapl/intel-rapl\:0/energy_uj
56039694184

Code: Added \ after intel-rapl\ to take into account unknown escape sequence

#define FILE_SIZE 512

static FILE *fp;
char filename[FILE_SIZE];

char TEMP[FILE_SIZE];
int FILE, READ;
long int POWER;

FILE = open("/sys/class/powercap/intel-rapl/intel-rapl\\:0/energy_uj", O_RDONLY);
READ = read(FILE, TEMP, sizeof(TEMP));
POWER= strtod(TEMP,NULL);
close(FILE);

sprintf(filename,"test.csv");
fp  = fopen(filename,"a+");
fprintf(fp,"\n");
fprintf(fp, "%ld", POWER);

The code compiles without any error, but in the output file I am getting value as 0. Is this due to how I am taking into account the escape sequence?

Thanks.

Chetan Arvind Patil
  • 854
  • 1
  • 11
  • 31
  • 1
    Why are you not checking for errors after open and read? – stark Aug 24 '17 at 22:08
  • 1
    Don't use the upper-case name `FILE` to mean anything other than the `FILE *` type from ``. It works, but it invites confusion and cannot be recommended, doubly so as you start by using `FILE` as a type name and then as a variable name. – Jonathan Leffler Aug 24 '17 at 22:12
  • In fact, upper-case names should normally be reserved for macros and constants (`#define` or `enum` constants). You don't know that the string returned by `read()` from the file is null terminated — it probably isn't. You should consider the merits of `TEMP[READ] = '\0';` after the `read()` and before the `strtod()`. – Jonathan Leffler Aug 24 '17 at 22:18
  • @stark - I am getting `Bad file descriptor` error. Is this due to `escape character` or I should change access to `O_RDWR`? – Chetan Arvind Patil Aug 24 '17 at 22:24
  • FWIW on my Ubuntu 16.04 Linux system, the file I think you are referencing is "/sys/devices/virtual/powercap/intel-rapl/intel-rapl:0/energy_uj " ... Note: no escapes... – TonyB Aug 24 '17 at 22:39
  • @TonyB - I am on `CentOS Linux 7 (Core)`. It still has escape character in `/sys/devices/virtual/powercap/intel-rapl/intel-rapl\:0/energy_uj` – Chetan Arvind Patil Aug 24 '17 at 23:32
  • It appears you are assuming TEMP will contain a "string" after read()...but you never initialized TEMP. try doing a "memset(TEMP, 0x00, sizeof(TEMP))" before performing the read(). – TonyB Aug 25 '17 at 08:13

1 Answers1

4

Since the sysfs files, while 'files' in one sense, may also be nodes, etc.. and not traditional text files, it is often best to let the shell interact with the sysfs files and simply read the needed values from a pipe following a call to popen using the shell command, e.g.

#include <stdio.h>

int main (void) {

    long unsigned energy_uj = 0;
    FILE *proc = popen (
        "cat /sys/class/powercap/intel-rapl/intel-rapl\\:0/energy_uj", "r");

    if (!proc) {  /* validate pipe open for reading */
        fprintf (stderr, "error: process open failed.\n");
        return 1;
    }

    if (fscanf (proc, "%lu", &energy_uj) == 1)  /* read/validate value */
        printf ("energy_uj: %lu\n", energy_uj);

    pclose (proc);

    return 0;
}

Example Use/Output

$ ./bin/sysfs_energy_uj
energy_uj: 29378726782

That's not to say you cannot read from the sysfs files directly, but if you have any problems, then reading from a pipe is fine. For the energy_uj value, it can be read directly without issue:

#include <stdio.h>

int main (void) {

    long unsigned energy_uj = 0;
    FILE *fp = fopen (
        "/sys/class/powercap/intel-rapl/intel-rapl:0/energy_uj", "r");

    if (!fp) {  /* validate file open for reading */
        fprintf (stderr, "error: file open failed.\n");
        return 1;
    }

    if (fscanf (fp, "%lu", &energy_uj) == 1)  /* read/validate value */
        printf ("energy_uj: %lu\n", energy_uj);

    fclose (fp);

    return 0;
}

Example Use/Output

$ ./bin/sysfs_energy_uj_file
energy_uj: 33636394660
David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • what would the overhead be? I am wondering if there is a better method than `read` at some sampling rate. efficiency is a problem when `read` is done on power readings and too many reads cause the CPU to burst.. causing systemic error/spike in power readings – Bilal Siddiqui Apr 28 '21 at 12:01
  • 1
    @BilalSiddiqui the difference in efficiency between reading from sysfs directly or reading the result of a shell query from a pipe would be barely discernible. The point being that without quite a bit more code in C, you cannot determine whether the sysfs file is an actual file or a special node. – David C. Rankin Apr 28 '21 at 19:05