0

I am trying to read proc file /proc/stat at periodic interval but I want to avoid having to open and close the proc file each time I want to access it.

I want to open the file in sort of init function, and then keep using it in some other function, then close it later on.

It seems file handles opened by a function gets closed when the function exits How can I keep it open ?

Please let me know if I should be doing it in some other manner

Sample of what I am trying to do:

#include <stdio.h>

int printer(FILE* fin)
{
  /* I am getting fin as NULL */
  if(!fin)
    return 1;

  char buf[16*1024];
  rewind(fin);
  size_t sz = fread(buf, 1, sizeof(buf), fin);
  if (sz) {
    buf[sz]=0;
    printf(buf);
  }

  return 0;
}

int opener(FILE *fin)
{
  fin = fopen("/proc/stat", "r");
  if (!fin) {
    perror("fopen");
    return 1;
  }

  return 0;
}

int main() {
  FILE *fin;
  /* 
   * I know it works if I open the file handle in here instead of
   * in another function but I want to avoid this
   */
  if(opener(fin)) 
  {
      printf("ERROR1\n");
      return 0;
  }

  while(1) {
    if(printer(fin))
    {   
      printf("ERROR2\n");
      break;
    }   
    sleep(1);
  }
  return 0;
}
L Lawliet
  • 2,565
  • 4
  • 26
  • 35

3 Answers3

2

Functions in c are pass by value. So when you pass a file handle to a function, it receives a copy of that handle and will update it locally. If you want those updates to propagate to your caller, you need pass file handle pointers. So your open would look like:

int opener(FILE **fin)
{
  *fin = fopen("/proc/stat", "r");
  if (!(*fin)) {
    perror("fopen");
    return 1;
  }

  return 0;
}

And you would call it like:

int main() {
  FILE *fin;
  /* 
   * I know it works if I open the file handle in here instead of
   * in another function but I want to avoid this
   */
  if(opener(&fin)) 
  {
      printf("ERROR1\n");
      return 0;
  }
/...
}
Red Alert
  • 3,786
  • 2
  • 17
  • 24
0

You need to pass a reference to the pointer to fin in order to keep it in main.

if(opener(&fin)) {}

pass it as double pointer :

int opener(FILE **fin) {}

and use it with derefencing

*fin = fopen("/proc/stat", "r");

otherwise you initiate it everytime you call your subfonction.

Pierre-Alexis Ciavaldini
  • 3,369
  • 1
  • 14
  • 16
0

The C language passes arguments by value, so the fin that opener has is a copy of the fin that main has. Changing fin in opener has no effect on main's copy.

One solution is to use a temporary file pointer in opener and then return that pointer. To indicate an error, return NULL.

FILE *opener( char *name )
{
    FILE *temp = fopen( name, "r" );
    if ( !temp )
    {
        perror( "fopen" );
        return( NULL );
    }
    return( temp );
}

int main( void )
{
    FILE *fin = opener( "/proc/stat" );

    if ( !fin )
        printf( "failed\n" );
    else
        printf( "fin=%p\n", fin );
}
user3386109
  • 34,287
  • 7
  • 49
  • 68