написать в файл (write on a file)
Обоснование (Rationale)
See also the RATIONALE section in read().
An attempt to write to a pipe or FIFO has several major
characteristics:
* Atomic/non-atomic: A write is atomic if the whole amount
written in one operation is not interleaved with data from
any other process. This is useful when there are multiple
writers sending data to a single reader. Applications need to
know how large a write request can be expected to be
performed atomically. This maximum is called {PIPE_BUF}.
This volume of POSIX.1‐2017 does not say whether write
requests for more than {PIPE_BUF} bytes are atomic, but
requires that writes of {PIPE_BUF} or fewer bytes shall be
atomic.
* Blocking/immediate: Blocking is only possible with O_NONBLOCK
clear. If there is enough space for all the data requested to
be written immediately, the implementation should do so.
Otherwise, the calling thread may block; that is, pause until
enough space is available for writing. The effective size of
a pipe or FIFO (the maximum amount that can be written in one
operation without blocking) may vary dynamically, depending
on the implementation, so it is not possible to specify a
fixed value for it.
* Complete/partial/deferred: A write request:
int fildes;
size_t nbyte;
ssize_t ret;
char *buf;
ret = write(fildes, buf, nbyte);
may return:
Complete ret=nbyte
Partial ret<nbyte
This shall never happen if nbyte≤{PIPE_BUF}. If it
does happen (with nbyte>{PIPE_BUF}), this volume of
POSIX.1‐2017 does not guarantee atomicity, even if
ret≤{PIPE_BUF}, because atomicity is guaranteed
according to the amount requested, not the amount
written.
Deferred: ret=-1, errno=[EAGAIN]
This error indicates that a later request may
succeed. It does not indicate that it shall
succeed, even if nbyte≤{PIPE_BUF}, because if no
process reads from the pipe or FIFO, the write
never succeeds. An application could usefully count
the number of times [EAGAIN]
is caused by a
particular value of nbyte>{PIPE_BUF} and perhaps do
later writes with a smaller value, on the
assumption that the effective size of the pipe may
have decreased.
Partial and deferred writes are only possible with O_NONBLOCK
set.
The relations of these properties are shown in the following
tables:
┌───────────────────────────────────────────────────────────────────────┐
│ Write to a Pipe or FIFO with O_NONBLOCK
clear │
├─────────────────────┬─────────────────────────────────────────────────┤
│Immediately Writable:
│ None Some
nbyte │
├─────────────────────┼─────────────────────────────────────────────────┤
│nbyte≤{PIPE_BUF} │Atomic blocking Atomic blocking Atomic immediate │
│ │nbyte nbyte nbyte │
├─────────────────────┼─────────────────────────────────────────────────┤
│nbyte>{PIPE_BUF} │Blocking nbyte Blocking nbyte Blocking nbyte │
└─────────────────────┴─────────────────────────────────────────────────┘
If the O_NONBLOCK flag is clear, a write request shall block if
the amount writable immediately is less than that requested. If
the flag is set (by fcntl()), a write request shall never block.
┌───────────────────────────────────────────────────────────────┐
│ Write to a Pipe or FIFO with O_NONBLOCK
set │
├─────────────────────┬─────────────────────────────────────────┤
│Immediately Writable:
│ None Some
nbyte │
├─────────────────────┼─────────────────────────────────────────┤
│nbyte≤{PIPE_BUF} │-1, [EAGAIN] -1, [EAGAIN] Atomic nbyte │
├─────────────────────┼─────────────────────────────────────────┤
│nbyte>{PIPE_BUF} │-1, [EAGAIN] <nbyte or -1, ≤nbyte or -1, │
│ │ [EAGAIN] [EAGAIN] │
└─────────────────────┴─────────────────────────────────────────┘
There is no exception regarding partial writes when O_NONBLOCK is
set. With the exception of writing to an empty pipe, this volume
of POSIX.1‐2017 does not specify exactly when a partial write is
performed since that would require specifying internal details of
the implementation. Every application should be prepared to
handle partial writes when O_NONBLOCK is set and the requested
amount is greater than {PIPE_BUF}, just as every application
should be prepared to handle partial writes on other kinds of
file descriptors.
The intent of forcing writing at least one byte if any can be
written is to assure that each write makes progress if there is
any room in the pipe. If the pipe is empty, {PIPE_BUF} bytes must
be written; if not, at least some progress must have been made.
Where this volume of POSIX.1‐2017 requires -1 to be returned and
errno set to [EAGAIN]
, most historical implementations return
zero (with the O_NDELAY flag set, which is the historical
predecessor of O_NONBLOCK, but is not itself in this volume of
POSIX.1‐2017). The error indications in this volume of
POSIX.1‐2017 were chosen so that an application can distinguish
these cases from end-of-file. While write() cannot receive an
indication of end-of-file, read() can, and the two functions have
similar return values. Also, some existing systems (for example,
Eighth Edition) permit a write of zero bytes to mean that the
reader should get an end-of-file indication; for those systems, a
return value of zero from write() indicates a successful write of
an end-of-file indication.
Implementations are allowed, but not required, to perform error
checking for write() requests of zero bytes.
The concept of a {PIPE_MAX} limit (indicating the maximum number
of bytes that can be written to a pipe in a single operation) was
considered, but rejected, because this concept would
unnecessarily limit application writing.
See also the discussion of O_NONBLOCK in read().
Writes can be serialized with respect to other reads and writes.
If a read() of file data can be proven (by any means) to occur
after a write() of the data, it must reflect that write(), even
if the calls are made by different processes. A similar
requirement applies to multiple write operations to the same file
position. This is needed to guarantee the propagation of data
from write() calls to subsequent read() calls. This requirement
is particularly significant for networked file systems, where
some caching schemes violate these semantics.
Note that this is specified in terms of read() and write(). The
XSI extensions readv() and writev() also obey these semantics. A
new ``high-performance'' write analog that did not follow these
serialization requirements would also be permitted by this
wording. This volume of POSIX.1‐2017 is also silent about any
effects of application-level caching (such as that done by
stdio).
This volume of POSIX.1‐2017 does not specify the value of the
file offset after an error is returned; there are too many cases.
For programming errors, such as [EBADF]
, the concept is
meaningless since no file is involved. For errors that are
detected immediately, such as [EAGAIN]
, clearly the pointer
should not change. After an interrupt or hardware error, however,
an updated value would be very useful and is the behavior of many
implementations.
This volume of POSIX.1‐2017 does not specify the behavior of
concurrent writes to a regular file from multiple threads, except
that each write is atomic (see Section 2.9.7, Thread Interactions
with Regular File Operations). Applications should use some form
of concurrency control.
This volume of POSIX.1‐2017 intentionally does not specify any
pwrite() errors related to pipes, FIFOs, and sockets other than
[ESPIPE]
.