1

Hi I'm writting a char driver that reads and writes to a particular device. Since I'm a noob, this is a very simple and easy char drive that only utilizes the simplest of protocols such as open, read, write, and release. To test my driver I am using the following program ... bellow is the source for my user-space program.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <signal.h>
#include <poll.h>

int main(void){
int num;
char *buff;
FILE *fd = fopen("/dev/hi","a+");
num = fprintf(fd,"this is sentence 1 !!");
num = fprintf(fd,"this is sentence 2 !!");
num = fprintf(fd,"this is sentence 3 !!");
num = fprintf(fd,"this is sentence 4 !!");
num = fprintf(fd,"this is sentence 5 !!");
buff = malloc(sizeof(char) * num+1);
fread(buff,sizeof(char),num+1,fd);
printf("%s\n",buff);
fread(buff,sizeof(char),num+1,fd);
printf("%s\n",buff);
fread(buff,sizeof(char),num+1,fd);
printf("%s\n",buff);
fread(buff,sizeof(char),num+1,fd);
printf("%s\n",buff);
fread(buff,sizeof(char),num+1,fd);
printf("%s\n",buff);
free(buff);
close(fd);
return 0;
}

Now its not important how my driver works but, in what order that I call my read and write methods. Ideally, it would be nice if the driver was being written to in the order that I've written my code and read from in the order that I've wrote my code. However I've noticed that if I have written my code like ...

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <signal.h>
#include <poll.h>

int main(void){
int num;
char *buff;
FILE *fd = fopen("/dev/hi","w");
num = fprintf(fd,"this is sentence 1 !!");
num = fprintf(fd,"this is sentence 2 !!");
num = fprintf(fd,"this is sentence 3 !!");
num = fprintf(fd,"this is sentence 4 !!");
num = fprintf(fd,"this is sentence 5 !!");
    close(fd);
    fd = fopen("/dev/hi","r");
buff = malloc(sizeof(char) * num+1);
fread(buff,sizeof(char),num+1,fd);
printf("%s\n",buff);
fread(buff,sizeof(char),num+1,fd);
printf("%s\n",buff);
fread(buff,sizeof(char),num+1,fd);
printf("%s\n",buff);
fread(buff,sizeof(char),num+1,fd);
printf("%s\n",buff);
fread(buff,sizeof(char),num+1,fd);
printf("%s\n",buff);
free(buff);
close(fd);
return 0;
}

I notice that fprintf() only writes when I close the file descriptor and worst yet, executes after I read from my device. Of course I want to write to my device and then read from it but it doesn't happen in order that. This gives me the impression that many things in user-space execute at the same time which baffles me. How do I know the order of which my device functions get called when dealing with user space. Sorry if this seems vague, I'll elaborate on anything that is mirky.

Thanks for any replies!!

Dr.Knowitall
  • 10,080
  • 23
  • 82
  • 133

4 Answers4

4

Your writes to 'fd' are being cached and only written to the device driver after you close it. This is normal and done to reduce the number of system calls.

If you really need each write to be sent to the device try adding a call to fsync() after each write. Alternatively, since it's a char driver it is most likely being line buffered, try adding a '\n' at the end of each line.

Kristof Provost
  • 26,018
  • 2
  • 26
  • 28
2

The code in user-space is executed in order (except you work explicit with parallelism or some other concept that mixes up the order).

I suspect that, what you interpret as "mirky" comes from the buffering of the fprintf.

You can flush the buffers by calling fflush(fd) after each fprintf. And you can disable it complete when you call beforehand setbuf(fd, NULL).

flolo
  • 15,148
  • 4
  • 32
  • 57
1

Look into fflush or fsync to flush out buffered output, and commit writes before doing your reads.

abelenky
  • 63,815
  • 23
  • 109
  • 159
0

As others have said, it's about buffering, and not some strange execution order effects. Use fflush to flush the stream and actually write the data, or use the lower-level open, write etc calls.

But another thing that I think should be pointed out:

You seem to have some confusion going on about streams and file descriptors. You call your FILE* "fd", and then say it's a file descriptor. But a FILE* is a stream, not a file descriptor. A file descriptor is a lower-level thing, which is hidden by the stdio library.

Linux provides file descriptors, which you get by calling open, and then you can use write to write to that file descriptor, and close it with close. The stdio library adds another level, with its own calls (fopen, fwrite, fprintf, fclose etc), and its own buffering, on top of the file descriptors.

Also note that you should use fclose to close the stream, not close.

Thomas Padron-McCarthy
  • 27,232
  • 8
  • 51
  • 75