Re: Problems with read() on /proc/devices with x86_64 system

From: Martin Schlemmer
Date: Wed Feb 22 2006 - 16:20:54 EST


On Wed, 2006-02-22 at 15:43 -0500, linux-os (Dick Johnson) wrote:
> On Wed, 22 Feb 2006, Martin Schlemmer wrote:
>
> > Hi,
> >
> > Not sure when it started, but 2.6.16-rc[1234] at least have problems
> > with unbuffered read() and /proc/devices on my x86_64 box. I first
> > picked it up with dmsetup that did not want to work properly built
> > against klibc (glibc with fread() worked fine though, as it mmap()'d the
> > file).
> >
> > Following code (from HPA and klibc mailing lists), when compiled and run
> > with /proc/devices only reads the first two lines and then exits
> > normally, where with any other file works as expected.
> >
> > -----
> > #include <stdlib.h>
> > #include <stdio.h>
> > #include <unistd.h>
> > #include <fcntl.h>
> > #include <errno.h>
> > #include <sys/stat.h>
> >
> > int main(int argc, char *argv[])
> > {
> > char c;
> > int i, fd, rv;
> >
> > for ( i = 1 ; i < argc ; i++ ) {
> > fd = open(argv[i], O_RDONLY);
> > if ( fd < 0 ) {
> > perror(argv[i]);
> > exit(1);
> > }
> >
> > while ( (rv = read(fd, &c, 1)) ) {
> > if ( rv == -1 ) {
> > if ( errno == EINTR || errno == EAGAIN )
> > continue;
> >
> > perror(argv[i]);
> > exit(1);
> > }
> > putchar(c);
> > }
> >
> > close(fd);
> > }
> > return 0;
> > }
> > -----
> >
> > Output over here:
> >
> > -----
> > # ./readbychar.klibc /proc/devices
> > Character devices:
> > 1 mem
> > #
> > -----
> > Thanks,
> > Martin Schlemmer
>
> If your code ever worked, it's probably because of some
> fortuitous buffering in the 'C' runtime library.

Not my code .. I just did a minimal hack to get it to build with klibc
(klibc do not support fscanf(), so used fread() and sscanf() ..).

> Most
> of the 'read' code in drivers that have a /proc interface
> is not designed for 1-character-at-a-time I/O. It's expected
> that it will be accessed like `cat` or `more` or other
> such tools access it, -- one read with 4096-byte buffer --
>
> read(3, "MemTotal: 773860 kB\nMemFre"..., 4096) = 670
> write(1, "MemTotal: 773860 kB\nMemFre"..., 670) = 670
>

Maybe, but the same code I posted works fine with any other file
in /proc, and works fine on my small p3 server with 2.6.14.

> The read code uses sprintf to write all the parameters to
> a buffer, then it copies the parameters to the user. The
> next read will return 0 for EOF and reset the interface
> for the next access.
>
> If your code read /proc without any help from the 'C' runtime
> library, you would read the same first character, every time
> you attempted to read a character. Don't do that! Your code
> should do (with some error-checking):
>
> fd = open(argv[1], O_RDONLY);
> buffer = malloc(LEN);
> read(fd, buffer, len);
> puts(buffer);
>
> Also, something seems somewhat strange because it is not
> commonplace to provide a mmap() interface to /proc file-system
> capability in drivers and the /proc base code doesn't
> provide memory-map capability at least on 2.6.15.4. So,
> your reference to memory-mapping the file seems to be
> incorrect.
>

Might have misread the strace there.



Thanks,

--
Martin Schlemmer

Attachment: signature.asc
Description: This is a digitally signed message part