write , writex , write64x, writev , writevx , ewrite , ewritev , pwrite 或 pwritev 子例程
用途
写入到文件。
库
| 项 | 描述 |
|---|---|
| 写, 写, write64x, 写, 写 Vx, 普文, pwritev | 标准 C 库 (libc.a) |
| 电子写, Ewritev | MLS 库 (libmls.a) |
语法
#include <unistd.h> ssize_t write (FileDescriptor, Buffer, NBytes)
int FileDescriptor;
const void * Buffer;
size_t NBytes;
int writex (FileDescriptor, Buffer, NBytes, Extension)
int FileDescriptor;
char *Buffer;
unsigned int NBytes;
int Extension;
int write64x (FileDescriptor, Buffer, NBytes, Extension)
int FileDescriptor;
void *Buffer;
size_t NBytes;
void *Extension;
ssize_t pwrite (FileDescriptor, Buffer, NBytes, Offset)
int FileDescriptor;
const void * Buffer;
size_t NBytes;
off_t Offset; #include <sys/uio.h> ssize_t writev (FileDescriptor, iov, iovCount)
int FileDescriptor;
const struct iovec * iov;
int iovCount;
ssize_t writevx (FileDescriptor, iov, iovCount, Extension)
int FileDescriptor;
struct iovec *iov;
int iovCount;
int Extension; #include <unistd.h>
#include <sys/uio.h> ssize_t pwritev (
int FileDescriptor,
const struct iovec * iov,
int iovCount,
offset_t offset);
ssize_t ewrite (FileDescriptor, Buffer, Nbytes, labels)
int FileDescriptor;
const void * Buffer;
size_t NBytes;
sec_labels_t * labels;
ssize_t ewritev (FileDescriptor, iov, iovCount,labels)
int FileDescriptor;
const struct iovec * iov;
int iovCount;
sec_labels_t * labels;
描述
write 子例程尝试将 NBytes 参数指定的数据字节数从 Buffer 参数指向的缓冲区写入与 FileDescriptor 参数关联的文件。
writev 子例程运行相同的操作,但从由 iov 参数指向的 iovec 结构数组指定的 iovCount 缓冲区收集输出数据。 每个 伊奥韦茨 条目都指定从其写入数据的内存中区域的基地址和长度。 写 子例程总是在前进到下一个之前写一个完整区域。
写 和 写 Vx 子例程与 写 和 写 子例程相同,但添加了 扩展 参数,该参数用于写入某些设备驱动程序。
有了常规文件和能够查找的设备,数据的实际写入将从文件指针所指示的文件中的位置继续进行。 从 写 子例程返回时,文件指针将按写入的字节数递增。
有无法寻找的设备,写总是从当前位置开始。 未定义与此类设备关联的文件指针的值。
如果 写 请求写入的字节数超过存在的空间 (例如, 乌勒明 或介质的物理端) ,那么仅写入的字节数与有空间的字节数相同。 例如,假设在文件达到限制之前,文件中还有 20 个字节的空间可用。 一个 512 字节的 写 将返回 20。 下一次写入非零字节数将返回失败 (当前主题中记录的情况除外) ,并且实现会为线程生成 SIGXFSZ 信号。
如果没有足够的空间来满足请求,那么可以写入的字节数少于请求的字节数。 此处,将返回写入的字节数。 下一次尝试写入非零字节数失败 (以下文本中另有说明的情况除外)。 达到的限制可以是由 乌勒明 子例程设置的限制,也可以是物理介质的结束。
如果以下条件全部为真,则成功完成写入子程序后会清除文件的SetUserID位(S_ISUID):
- 调用过程不具有 root 用户权限。
- 调用进程的有效用户标识与该文件的用户标识不匹配。
- 该文件可由组 (_IXGRP) 或其他 (_IXOTH) 执行。
如果以下条件全部为真,写入子程序将清除SetGroupID位(S_ISGID):
- 调用过程不具有 root 用户权限。
- 该文件的组标识与该进程的有效组标识或其中一个补充组标识不匹配。
- 该文件可由所有者 ((_IXUSR)) 或其他用户 (_IXOTH) 执行。
如果设置了文件状态的 O_APPEND 标志,那么在每次写入之前,文件偏移量将设置为文件结束。
如果 FileDescriptor 参数引用其文件状态标志指定了 O_SYNC的常规文件,那么此操作是同步更新 (如 open 子例程中所述)。
如果 FileDescriptor 参数引用进程在设置了 O_延迟 文件状态标志的情况下打开的常规文件,那么直到进程发出 fsync 子例程或执行同步更新之后,才会在永久存储器上更新数据和文件大小。 如果所有使用 0-DEFER 文件状态标志设置打开文件的进程在进程发出 Fsync 子例程或执行同步更新之前关闭该文件,那么不会在永久存储器上更新数据和文件大小。
对管道 (或先进先出 (FIFO)) 的写请求的处理与常规文件相同,但存在以下异常:
- 不存在与管道关联的文件偏移量; 因此,每个写请求都附加到管道的末尾。
- 如果写请求的大小小于或等于 PIPE_BUF 系统变量的值 (在 路径配置 例程中进行了描述) ,那么 写 子例程是自动的。 数据不会与来自同一管道上其他写进程的数据交织在一起。 大于 PIPE_BUF 字节的写操作可以具有交错的数据 (在任意边界上) 以及其他进程的写操作 (无论是否设置了 O_NDELAY 或 O_NONBLOCK 文件状态标志)。
- 如果清除 O_NDELAY 和 O_NONBLOCK 文件状态标志 (缺省值) ,那么对完整管道的写请求会导致进程阻塞,直到有足够的空间可用于处理整个请求为止。
- 如果设置了 O_NDELAY 文件状态标志,那么对完整管道的写操作将返回 0。
- 如果设置了 O_NONBLOCK 文件状态标志,那么写入完整管道将返回值 -1 ,并将 errno 全局变量设置为 EAGAIN。
当系统尝试写入支持非阻塞写操作的字符特殊文件并且当前无法写入任何数据时 (流是稍后描述的异常):
- 如果 O_NDELAY 和 O_NONBLOCK 标志是清除的 (缺省值) ,那么 写 子例程会阻塞直到可以写入数据为止。
- 如果设置了 O_NDELAY 标志,那么 写 子例程返回 0。
- 如果设置了 O_NONBLOCK 标志,那么 write 子例程将返回 -1 并将 errno 全局变量设置为 EAGAIN (如果无法写入任何数据)。
当系统尝试写入支持强制方式记录锁定的常规文件,并且要写入的区域的全部或部分被另一个进程锁定时,可能会发生下列情况:
- 如果清除了 O_NDELAY 和 O_NONBLOCK 文件状态标志 (缺省值) ,那么调用进程将阻塞到释放锁定为止。
- 如果设置了 O_NDELAY 或 O_NONBLOCK 文件状态标志,那么 写 子例程将返回值 -1 并将 埃尔诺 全局变量设置为 再次。
如果 菲尔德斯 指的是 STREAM ,那么 写 的操作由 STREAM 接受的最小和最大 nbyte 范围 ("包大小") 的值确定。 这些值由最顶层的 STREAM 模块确定。 如果 nbyte 在包大小范围内,那么将写入 nbyte 个字节。 如果 nbyte 不在此范围内,并且最小包大小值为 0 ,那么 写 在将数据发送到下游之前将缓冲区分为最大包大小段 (最后一个段包含小于最大包大小的数据)。 如果 nbyte 不在此范围内,并且最小值为非零,那么 写 将失败并将 错误号 设置为 ERANGE。 向 STREAMS 设备写入零长度缓冲区 (nbyte 为 0) 将发送 0 个字节,并返回 0 个字节。 但是,将零长度缓冲区写入基于 STREAMS 的管道或 FIFO 不会发送任何消息,并且会返回 0 。 该进程可以发出 I_SWROPT ioctl ,以允许通过管道或 FIFO 发送零长度消息。
当系统写入 STREAM 时,将以 0 作为优先级频带来创建数据消息。 当它写入到不是管道或 FIFO 的 STREAM 时:
- O_NONBLOCK 指定 O_NONBLOCK 或 O_NDELAY。 IBM®streams 实现对这两者的处理方式相同。
- 如果 O_NONBLOCK 或 O_NDELAY 已清除,并且 STREAM 无法接受数据 (由于内部流量控制条件, STREAM 写队列已满) ,那么 写 将阻塞到可以接受数据为止。
- 如果设置了 O_NONBLOCK 或 O_NDELAY ,并且 STREAM 无法接受数据,那么 写 将返回 -1 并将 埃尔诺 设置为 再次。
- 如果设置了 O_NONBLOCK 或 O_NDELAY ,并且写入了部分缓冲区,但出现了 STREAM 无法接受更多数据的情况,那么 写 将结束并返回写入的字节数。
此外,如果 STREAM 头在调用之前处理异步错误,那么 写 和 写 将失败。 此处, 错误号 的值不会反映 写 或 写 的结果,但会反映先前的错误。
写 函数等效于 写,但会从由成员指定的 iovcnt 缓冲区中收集输出数据。 iov 数组 :iov [0] , iov [1] , ... , iov [1-1]. 如果大于 0 且小于或等于 limits.h中定义的 {IOV_MAX},那么 iovcnt 有效。
每个 伊奥韦茨 条目都指定从其写入数据的内存中区域的基地址和长度。 写 函数在前进到下一个之前始终写入一个完整区域。
如果 菲尔德斯 是指常规文件,并且 伊奥夫 所指向的数组中的所有 iov_len 成员都是 0,那么 写 将返回 0 并且没有其他影响。 对于其他文件类型,行为未指定。
如果 iov_len 值的总和大于 最大 SSIZE_MAX,那么该操作将失败,并且不会传输任何数据。
中断的 写 子例程的行为取决于安装到达信号的处理程序的方式。 该处理程序可以通过以下两种方式之一进行安装,并产生以下结果:
- 如果安装处理程序时指示未重新启动子例程,那么 write 子例程将返回值 -1 并将 errno 全局变量设置为 EINTR (即使已写入某些数据)。
- 如果该处理程序已安装并指示要重新启动子例程,并且:
- 如果在处理中断时没有写入任何数据,那么 写 子例程不会返回值 (它将重新启动)。
- 如果在处理中断时写入数据,那么此 写 子例程返回已写入的数据量。
write64x 子例程与 写 子例程相同,其中 扩展 参数是一个指向 j2_ext 结构的指针 (请参阅 j2/j2_cntl.h 文件)。 write64x 子例程用于以原始方式写入加密文件 (请参阅 fcntl.h 文件中的 O_RAW )。 在加密文件上使用 0-RAW 标志具有与在常规文件上使用 重定向 相同的限制。
电子写 和 Ewritev 子例程将写入流并设置安全性属性。 ewrite 子例程将 Nbyte 参数指定的数据字节数从 Buffer 参数指向的缓冲区复制到与 FileDescriptor 参数关联的流。 消息的安全信息将设置为 标签 参数所指向的结构中的值。
普文 函数执行与 写相同的操作,但它在不更改文件指针的情况下写入到给定位置。 普文 的前三个自变量与 写 相同,但添加了第四个自变量,该自变量对于文件中的所需位置而言是偏移的。
ssize_t pwrite64(int fd , const void *buf , size_t nbytes , off64_t offset)pwrite64 子例程执行与 pwrite 相同的操作,但如果与 fileDescriptor 关联的文件是块特殊文件或字符特殊文件,那么对于与 fileDescriptor 和 DEV_OFF_MAX 关联的文件,偏移量限制为最大文件大小。
将 写 或 普文 子例程与从对 Shm_open 子例程的调用中获取的文件描述符配合使用失败,并返回 ENXIO。
pwritev 子例程执行与 写 子例程相同的操作,只不过 pwritev 子例程在不更改文件指针的情况下写入文件中的给定位置。 pwritev 子例程的前三个自变量与 写 子例程相同,并添加了 偏移 自变量,该自变量指向您希望在文件中的位置。 当 pwritev 子例程写入的文件无法查找时,会发生错误。
参数
| 项 | 描述 |
|---|---|
| 缓冲区 | 确定包含要写入的数据的缓冲区。 |
| 扩展名 | 提供与需要更多信息或返回其他状态的字符设备驱动程序的通信。 每个驱动程序都以与设备相关的方式将 扩展 参数解释为值或指向通信区域的指针。 当 扩展 参数值为 0 时,驱动程序必须应用合理的缺省值。 |
| FileDescriptor | 标识要将数据写入到的对象。 |
| 伊奥夫 | 指向 伊奥韦茨 结构的数组,该数组用于标识包含要写入的数据的缓冲区。 iovec 结构在 sys/uio.h 文件中定义,并包含以下成员: |
| iovCount | 指定 伊奥夫 参数所指向的 伊奥韦茨 结构的数目。 |
| 字节数 | 指定要写入的字节数。 |
| 偏移量 | 文件中开始写操作的位置。 |
| 标签 | 指向扩展安全性属性结构的指针。 |
返回值
在成功完成时, 写, 写, write64x, 写和 写 Vx,和 pwritev 子例程将返回已写入的字节数。 写入的字节数永远不会超过 字节数 参数指定的值。 否则,将返回值 -1 ,并设置 errno 全局变量以指示错误。
在成功完成后, 电子写 和 Ewritev 子例程将返回值 0。 否则,会将全局变量 错误号 设置为标识错误。
错误代码
当下列其中一项或多项为 true 时, 写, 写, write64x, 写, 写 Vx, 电子写, Ewritev和 pwritev 子例程不成功:
| 项 | 描述 |
|---|---|
| EAGAIN | 在此文件上设置了 O_NONBLOCK 标志,并且该进程将在写操作中延迟; 或者在要写入的文件部分中存在未完成的强制方式记录锁定。 |
| EBADF | FileDescriptor 参数未指定打开用于写入的有效文件描述符。 |
| EDQUOT | 由于文件系统上磁盘块的用户或组配额已耗尽,因此无法为文件分配新的磁盘块。 |
| EFBIG | 在 32 位内核上请求了大于 MAX_FILESIZE 的偏移量。 |
| EFAULT | 缓冲区 参数或 伊奥夫 参数的部分指向进程的已分配地址空间之外的位置。 |
| EFBIG | 尝试写入超过进程文件大小限制或文件大小最大限制的文件。 如果用户在执行进程之前设置环境变量 XPG_SUS_ENV=ON ,那么当 SIGXFSZ 信号超过进程的文件大小限制时,会将该信号发布到进程。 |
| EINVAL | 与 FileDescriptor 参数关联的文件位置指针为负数; iovCount 参数值不是 1-16 (含); 或者 iov 数组中的一个 iov_len 值为负数。 |
| EINVAL | 在 32 位或 64 位内核环境中,来自 32 位应用程序的 iov_len 值的总和溢出了 32 位带符号整数,或者来自 64 位应用程序的 iov_len 值的总和溢出了 32 位内核环境中的 32 位带符号整数。 |
| EINVAL | 文件描述符引用的 STREAM 或多路复用器(直接或间接)链接到多路复用器的下游。 |
| EINVAL | 在 32 位内核上,请求了大于 最大偏移量的 字节数 参数的值。 在此,系统调用是从正在 32 位内核上运行的 64 位应用程序请求的。 |
| EINTR | 在执行写操作期间捕获到信号,并且安装了信号处理程序,并指示不重新启动子例程。 |
| EIO | 在系统写入文件系统时发生 I/O 错误; 或者该进程是尝试写入其控制终端的后台进程组的成员,设置了 停止 ,该进程未忽略或阻止 SIGTTOU,并且该进程组没有父进程。 |
| ENOSPC | 在包含该文件的文件系统上没有剩余可用空间。 |
| ENXIO | 正在写入的 STREAM 上发生了挂断。 写 或 普文 子例程与从对 Shm_open 子例程的调用中获取的文件描述符一起使用。 |
| EPIPE | 尝试写入任何进程未打开以进行读取的文件,或未连接至对等套接字的类型为 SOCK_STREAM 的套接字; 或尝试写入任何进程未打开以进行读取的管道或 FIFO。 如果发生此情况,那么会向进程发送 SIGPIPE 信号。 |
| ERANGE | 传输请求大小超出与 FileDescriptor关联的 STREAMS 文件支持的范围。 |
如果以下情况成立,那么 写, 写, 写, 写 Vx和 pwritev 子例程可能不成功:
| 项 | 描述 |
|---|---|
| ENXIO | 对不存在的设备发出了请求,或者该请求超出了该设备的能力范围。 |
| EFBIG | 尝试写入常规文件,其中 NBytes 大于零且起始偏移量大于或等于与 FileDescriptor关联的打开文件描述中确定的最大偏移量。 |
| EINVAL | 偏移 参数是无效的。 值为负数。 |
| EsPIPE | 菲尔德斯 与一个管道或 FIFO 关联。 |
| 项 | 描述 |
|---|---|
| EINVAL | 未正确初始化结构 j2_ext 。 例如,版本不正确,或者文件未加密。 |
| EINVAL | 对于未以原始方式打开的文件,将通过使用 J2EXTCMD_RDRAW 命令来传递 j2_ext 结构。 |
| 项 | 描述 |
|---|---|
| ENOMEM | 内存或空间过少。 |
| EACCES | 许可权被拒绝。 用户没有足够的特权来写数据。 |
| ERESTART | ERESTART 用于确定系统调用是否是可重新启动的。 |