svn commit: r341803 - head/libexec/rc
Devin Teske
dteske at FreeBSD.org
Tue Dec 11 20:35:51 UTC 2018
> On Dec 11, 2018, at 11:57 AM, Conrad Meyer <cem at freebsd.org> wrote:
>
> On Tue, Dec 11, 2018 at 10:04 AM Warner Losh <imp at bsdimp.com> wrote:
>> On Tue, Dec 11, 2018, 9:55 AM John Baldwin <jhb at freebsd.org wrote:
>>>
>>> The 'read' builtin in sh can't use buffering, so it is always going to be slow
>>
>> It can't use it because of pipes. The example from the parts of this that was on IRC was basically:
>>
>> foo | (read bar; baz)
>>
>> Which reads one line into the bar variable and then sends the rest to the bar command.
>
> It can't trivially, but it's not impossible. sh could play games and
> buffer its own use of stdin, and then open a fresh pipe for stdin of
> subsequent non-builtins, writing out unused portions of the buffer.[A]
>
> Some other alternatives that would require kernel support but are
> things we've talked about doing in the kernel before anyway:
>
> * If we had something like eBPF programs attached to IO, maybe sh's
> read built-in could push a small eBPF program into the kernel that
> determined how many bytes could be read from the pipe in a single
> syscall without reading too far. It's fairly trivial. Simply
> returning a number of bytes up to and including the first '\n' would
> be a fine, if sometimes conservative amount. (Input lines can be
> continued with a trailing backslash, except in -r mode, but as a
> first-cut approximation, reading-until-newline is probably good
> enough.)[B]
>
> * Heck, even just a read_until_newline(2) syscall would work and
> probably be more broadly useful than just sh(1). I don't think it
> passes the sniff test — not general enough, and probably not something
> you want beginners stumbling across instead of fgets(3) — but it'd be
> fine, and there are other pipe-abusing programs that care about
> reading ASCII text lines without overconsuming input than just
> sh(1).[C]
>
> * If we had something like Linux's tee(2) system call (which is as it
> sounds — tee(1) for pipes), sh(1)'s read built-in could tee(2) for
> buffering without impacting stdin, and read(2) stdin only when it knew
> how many bytes were consumed (or when the pipe buffer became full).[D]
>
> I suspect (C) would be the easiest to implement correctly, followed by
> (D). (B) is requires some architectural design and bikeshedding and
> the details on the kernel side are tricky. (A) would be a little
> tricky and probably require extensive changes to sh(1) itself, which
> is a risk to the base system. But it would not impact the kernel.
>
> Is there any interest in a tee(2)-like syscall?
>
Linux has vmsplice(2). I know jmg@ also expressed interest in having a
vmsplice in FreeBSD.
As for sh not being able to read more than a single byte at a time because
it could be reading from a pipe, what if it read into a buffer and returned
a line from the buffer. A subsequent read would return more data from the
buffer, ad nauseam until the buffer runs out -- in which case another chunk
is read to augment the data.
This buffer could be expunged when stdin collapses (e.g., when the sub-
shell completes.
--
Devin
More information about the svn-src-all
mailing list