read() builtin doesnt read integer value /proc files (but bashs does)
Cristian Ionescu-Idbohrn
cristian.ionescu-idbohrn at axis.com
Sun Dec 19 10:56:24 UTC 2010
On Sun, 19 Dec 2010, Denys Vlasenko wrote:
> On Wednesday 15 December 2010 14:12, Cristian Ionescu-Idbohrn wrote:
> > On Wed, 15 Dec 2010, Bob Dunlop wrote:
> > >
> > > Not a fix but a work around:
> > >
> > > > $ ./busybox ash -c 'read MAX </proc/sys/kernel/pid_max; echo $MAX'
> > > > 3
> > >
> > > $ busybox ash -c 'MAX=$(cat /proc/sys/kernel/pid_max) ; echo $MAX'
> > > 32768
> > >
> > >
> > > Files in /proc are generated on the fly. They can be fussy about how
> > > they are read.
> >
> > Yes. Same suggestion as Herbert Xu's, who stated:
> >
> > 'a perfectly adequate work-around in "cat"'
> >
> > Unfortunately, that work around is neither perfect nor adequate. I'd call
> > it painful, as:
> >
> > read MAX </proc/sys/kernel/pid_max
> >
> > is so much more efficient (about 25x faster, on my box) than:
> >
> > MAX=$(cat /proc/sys/kernel/pid_max)
> >
> > I hope you noticed, this is a problem _only_ with /proc files holding
> > integers >9. No such problems with files containing strings.
>
> The fix is hard. Consider that read should work properly here:
>
> exec </proc/some/file
> read line
> cat
>
> If read "reads ahead" 128 bytes, but finds '\n' after 5th byte,
> how can it "roll back" so that cat starts reading at the right
> position?
Seems bash somehow manages to deliver what's expected:
$ strace bash -c 'read MAX </proc/sys/kernel/pid_max; echo $MAX'
...
open("/proc/sys/kernel/pid_max", O_RDONLY|O_LARGEFILE) = 3
fcntl64(0, F_GETFD) = 0
fcntl64(0, F_DUPFD, 10) = 10
fcntl64(0, F_GETFD) = 0
fcntl64(10, F_SETFD, FD_CLOEXEC) = 0
dup2(3, 0) = 0
close(3) = 0
ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, 0xbf8bd378) = -1 ENOTTY (Inappropriate ioctl for device)
_llseek(0, 0, [0], SEEK_CUR) = 0
read(0, "32768\n", 128) = 6
dup2(10, 0) = 0
fcntl64(10, F_GETFD) = 0x1 (flags FD_CLOEXEC)
close(10) = 0
write(1, "32768\n", 632768
) = 6
exit_group(0) = ?
$ strace bash -c 'exec </proc/sys/kernel/pid_max; read MAX; echo $MAX'
...
open("/proc/sys/kernel/pid_max", O_RDONLY|O_LARGEFILE) = 3
fcntl64(0, F_GETFD) = 0
fcntl64(0, F_DUPFD, 10) = 10
fcntl64(0, F_GETFD) = 0
fcntl64(10, F_SETFD, FD_CLOEXEC) = 0
dup2(3, 0) = 0
close(3) = 0
close(10) = 0
ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, 0xbff33748) = -1 ENOTTY (Inappropriate ioctl for device)
_llseek(0, 0, [0], SEEK_CUR) = 0
read(0, "32768\n", 128) = 6
write(1, "32768\n", 632768
) = 6
exit_group(0)
and Ralf provided relevant info earlier in the thread:
On Wed, 15 Dec 2010, Ralf Friedl wrote:
>
> Bash does single byte reads when both ioctl(TCGETS) and lseek fail, but
> 128 byte reads on regular files or tty.
Cheers,
--
Cristian
More information about the busybox
mailing list