How to force fgets read from file instead of buffer cache?

L

luke.yolanda

Hello everybody,

Actually, I'm trying to read (no write operation) from proc filesystem
periodically. It turns out that after first read, all subsequent read
are go to buffercache, not the proc fs (therefore, get the same value
every time). This problem can be avoided by closing and open it again
after each read, but I'm wondering if there's a better solution?

Thank you very much!

Gen
 
G

gwowen

Actually, I'm trying to read (no write operation) from proc filesystem
periodically. It turns out that after first read, all subsequent read
are go to buffercache, not the proc fs

If you are using Linux, I rather suspect this is not the problem. You
don't provide enought information to be any more helpful than that,
I'm afraid.
 
S

Seebs

Hello everybody,

Actually, I'm trying to read (no write operation) from proc filesystem
periodically. It turns out that after first read, all subsequent read
are go to buffercache, not the proc fs (therefore, get the same value
every time). This problem can be avoided by closing and open it again
after each read, but I'm wondering if there's a better solution?

"Buffer cache" is 99% likely to be the wrong term here, but details would
be system-specific.

Suggestion: Use setvbuf(). If that doesn't work, you'll need to bypass
stdio.

-s
 
L

luke.yolanda

If you are using Linux, I rather suspect this is not the problem.  You
don't provide enought information to be any more helpful than that,
I'm afraid.

first of all, thanks for your help.
yes, it's in linux. I just wrote a simplified version of my code, as
below:

/*************************** code start
***********************************/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>


#define PROC_PATH "/proc/self/net/dev"
//for you to make this work, change following macro to the name of the
device you used
#define DEV_NAME "wlan0"

#define PERIOD 2

int main(){
/*initialization*/
int bt;
int i, ret;
int stat[16];
char *linebuffer = (char *)malloc(256);
char *token = (char *)malloc(32);
if(!linebuffer || !token)
exit(-1);
FILE *fp_in;
fp_in = fopen(PROC_PATH, "r");
if(!fp_in)
exit(-2);
/*read specified entry*/
for(i=0;i<100;i++){
bt=0;
memset(linebuffer, 0, 256);
memset(token, 0, 32);

if(fgets(linebuffer, 256, fp_in)==NULL)
exit(-3);
ret = sscanf(linebuffer,
"%[ a-z0-9]: %d %d %d %d %d %d %d %d %d %d %d
%d %d %d %d %d \n",
token,

&stat[0],&stat[1],&stat[2],&stat[3],&stat[4],&stat[5],&stat[6],&stat[7],

&stat[8],&stat[9],&stat[10],&stat[11],&stat[12],&stat[13],&stat[14],&stat[15]);
while(*token==' '){
token++;
bt++;
}
printf("i %d token %s\n",i,token);
if(strcmp(token, DEV_NAME))
token -= bt;
else{
token -= bt;
printf("dev:%s\t recv:%d\t trans:%d\n",token, stat[0], stat[8]);

/*choice #1, close and reopen the file*/
fclose(fp_in);
fp_in = fopen(PROC_PATH, "r");
if(!fp_in)
exit(-2);
/*choice #2, rewind the pointer in the stream
back to the start*/
//rewind(fp_in);

sleep(PERIOD);

}
}
fclose(fp_in);
free(linebuffer);
free(token);
}

/*************************** code end
***********************************/

Please notice the choice #1 and #2 in my comment, when using #1,
everything's just fine, but after switch to #2 (using rewind(), hope I
didn't misunderstand its usage, since I've never used it before), it
will always get the same value over and over. It seems to me that the
fgets() never go to actual file system again after the first read, and
goes to buffer cache instead.

I will try to add some logging in kernel to see what's really going on
when I get time...

Thank you guys!

Gen
 
L

luke.yolanda

"Buffer cache" is 99% likely to be the wrong term here, but details would
be system-specific.

Suggestion:  Use setvbuf().  If that doesn't work, you'll need to bypass
stdio.

Hi,

setvbuf seems to be the solution, it works well for me now :)
Thanks!

Gen
 
J

James Dow Allen

setvbuf seems to be the solution, it works well for me now :)
Thanks!

It's good that you solved your problem. But ...
You *know* you're on Unix with code very much OS-dependent;
*why* would you ever choose fread() over read() in the first place?
The False Gods of Portability have led you astray.

(Historical note: I recall espousing read() over fread() for a similar
purpose about 2 decades ago in this ng, and was condemned by
Dan Pop who seemed to think that read() could only read 1 character
at a time!!)

James
 
J

James Dow Allen

... Dan Pop who seemed to think that read() could only read 1 character
at a time!!)

I clicked Send too hurriedly, misquoting Mr. Pop, whose point
seemed to be that a programmer smart enough to bypass fread()
for read() for certain OS-specific tasks, would then stupidly
use read(0, ..., 1) in preference to getc().

James
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,123
Latest member
Layne6498
Top