- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我想实现一个合适的 write(2)
循环接受一个缓冲区并不断调用 write
直到整个缓冲区被写入。
我想基本的方法是这样的:
/** write len bytes of buf to fd, returns 0 on success */
int write_fully(int fd, char *buf, size_t len) {
while (len > 0) {
ssize_t written = write(fd, buf, len);
if (written < 0) {
// some kind of error, probably should try again if its EINTR?
return written;
}
buf += written;
len -= written;
}
return 0;
}
...但这提出了一个问题,即 write()
是否可以有效地返回写入的 0 字节以及在这种情况下该怎么做。如果这种情况持续存在,上面的代码只会在 write
调用上热旋转,这似乎是个坏主意。只要返回不是零的,您就在取得进展。
write
的手册页有点模棱两可。它说,例如:
On success, the number of bytes written is returned (zero indicates nothing was written).
这似乎表明在某些场景下是可能的。只有一种这样的场景被明确指出:
If count is zero and fd refers to a regular file, then write() may return a failure status if one of the errors below is detected. If no errors are detected, or error detection is not performed, 0 will be returned without causing any other effect. If count is zero and fd refers to a file other than a regular file, the results are not specified.
上面避免了这种情况,因为我从不使用 len == 0
调用 write
。还有很多其他情况无法写入任何内容,但通常它们都有与之关联的特定错误代码。
文件本身将根据命令行中给出的路径/名称打开
。所以它通常是一个常规文件,但用户当然可以传递诸如管道之类的东西,进行输入重定向,传递诸如 /dev/stdout
之类的特殊设备等等。我至少可以控制 open
调用,并且 O_NONBLOCK
标志不会传递给 open。我无法合理地检查所有文件系统、所有特殊设备的行为(即使我可以,也会添加更多),所以我想知道如何以合理和通用的方式处理这个问题.
* ... 对于非零缓冲区大小。
最佳答案
除非您不顾一切地调用未指定的行为,否则您不会从 write()
返回零结果,除非您尝试写入零字节(问题中的代码避免这样做)。
我相信 write()
的 POSIX 规范涵盖了这个问题。
The write() function shall attempt to write nbyte bytes from the buffer pointed to by buf to the file associated with the open file descriptor, fildes.
Before any action described below is taken, and if nbyte is zero and the file is a regular file, the write() function may detect and return errors as described below. In the absence of errors, or if error detection is not performed, the write() function shall return zero and have no other results. If nbyte is zero and the file is not a regular file, the results are unspecified.
这说明如果您请求写入零字节,您可能会得到零返回值,但有一些警告 — 它必须是一个常规文件,如果像 EBADF
这样的错误是您可能会得到一个错误检测到,并且未指定如果文件描述符不引用常规文件会发生什么。
If a write() requests that more bytes be written than there is room for (for example, [XSI]⌦ the file size limit of the process or ⌫ the physical end of a medium), only as many bytes as there is room for shall be written. For example, suppose there is space for 20 bytes more in a file before reaching a limit. A write of 512 bytes will return 20. The next write of a non-zero number of bytes would give a failure return (except as noted below).
[XSI]⌦ If the request would cause the file size to exceed the soft file size limit for the process and there is no room for any bytes to be written, the request shall fail and the implementation shall generate the SIGXFSZ signal for the thread. ⌫
If write() is interrupted by a signal before it writes any data, it shall return -1 with errno set to [EINTR].
If write() is interrupted by a signal after it successfully writes some data, it shall return the number of bytes written.
If the value of nbyte is greater than {SSIZE_MAX}, the result is implementation-defined.
这些规则并没有真正允许返回 0(尽管学究可能会说太大的 nbyte
值可能被定义为返回 0)。
When attempting to write to a file descriptor (other than a pipe or FIFO) that supports non-blocking writes and cannot accept the data immediately:
If the O_NONBLOCK flag is clear, write() shall block the calling thread until the data can be accepted.
If the O_NONBLOCK flag is set, write() shall not block the thread. If some data can be written without blocking the thread, write() shall write what it can and return the number of bytes written. Otherwise, it shall return -1 and set errno to [EAGAIN].
…details for obscure file types — a number of them with unspecified behaviour…
Return value
Upon successful completion, these functions shall return the number of bytes actually written to the file associated with fildes. This number shall never be greater than byte. Otherwise, -1 shall be returned and errno set to indicate the error.
因此,由于您的代码避免尝试写入零字节,只要 len
不大于 {SSIZE_MAX},并且只要您不写入模糊的文件类型(如共享内存对象或类型化内存)对象)你不应该看到 write()
返回零。
稍后在 write()
的 POSIX 页面的基本原理部分中,有以下信息:
Where this volume of POSIX.1-2008 requires
-1
to be returned anderrno
set to [EAGAIN], most historical implementations return zero (with theO_NDELAY
flag set, which is the historical predecessor ofO_NONBLOCK
, but is not itself in this volume of POSIX.1-2008). The error indications in this volume of POSIX.1-2008 were chosen so that an application can distinguish these cases from end-of-file. Whilewrite()
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 fromwrite()
indicates a successful write of an end-of-file indication.
因此,尽管 POSIX(即使不是全部,也很大程度上)排除了从 write()
返回零的可能性,但相关系统上的现有技术确实使 write()
返回零。
关于write(2) 能否返回写入的 0 个字节*,如果返回怎么办?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41904221/
我有这个代码 var myChart = new FusionCharts("../themes/clean/charts/hbullet.swf", "myChartId", "400", "75
既然写入是立即进行的(复制到内核缓冲区并返回),那么使用 io_submit 进行写入有什么好处? 事实上,它 (aio/io_submit) 看起来更糟,因为您必须在堆上分配写入缓冲区并且不能使用基
我正在使用 mootool 的 Request.JSON 从 Twitter 检索推文。收到它后,我将写入目标 div 的 .innerHTML 属性。当我在本地将其作为文件进行测试时,即 file:
最终,我想将 Vertica DB 中的数据抓取到 Spark 中,训练机器学习模型,进行预测,并将这些预测存储到另一个 Vertica DB 中。 当前的问题是确定流程最后部分的瓶颈:将 Spark
我使用 WEKA 库编写了一个 Java 程序, 训练分类算法 使用经过训练的算法对未标记的数据集运行预测 将结果写入 .csv 文件 问题在于它当前写出离散分类结果(即算法猜测一行属于哪个类别)。我
背景 - 我正在考虑使用 clickonce 通过 clickonce(通过网站)部署 WinForms 应用程序。相对简单的应用程序的要素是: - 它是一个可执行文件和一个数据库文件(sqlite)
是否有更好的解决方案来快速初始化 C 数组(在堆上创建)?就像我们使用大括号一样 double** matrix_multiply(const double **l_matrix, const dou
我正在读取 JSON 文件,取出值并进行一些更改。 基本上我向数组添加了一些值。之后我想将其写回到文件中。当我将 JSONArray 写回文件时,会被写入字符串而不是 JSONArray 对象。怎样才
我为两个应用程序使用嵌入式数据库,其中一个是服务器,另一个是客户端。客户端应用程序。可以向服务器端发送获取数据请求以检索数据并显示在表格(或其他)中。问题是这样的:如何将获取的数据保存(写入)到页面文
是否有更好的解决方案来快速初始化 C 数组(在堆上创建)?就像我们使用大括号一样 double** matrix_multiply(const double **l_matrix, const dou
从问题得出问题:找到所有 result = new ArrayList(); for (int i = 2; i >(i%8) & 0x1) == 0) { result.add(i
由于某种原因,它没有写入 CSV。谁能明白为什么它不写吗? def main(): list_of_emails = read_email_csv() #read input file, cr
关闭。 这个问题是 not reproducible or was caused by typos 。它目前不接受答案。 这个问题是由于错别字或无法再重现的问题引起的。虽然类似的问题可能在这里出现,
我目前正在开发一个保存和加载程序,但我无法获得正确的结果。 编写程序: #include #include #define FILENAME "Save" #define COUNT 6 type
import java.io.*; public class Main2 { public static void main(String[] args) throws Exception {
我需要使用预定义位置字符串“Office”从所有日历中检索所有 iOS 事件,然后将结果写入 NSLog 和 UITextView。 到目前为止,这是我的代码: #import "ViewCo
我正在尝试将 BOOL 值写入 PFInstallation 中的列,但会不停地崩溃: - (IBAction)pushSwitch:(id)sender { NSUserDefaults *push
我以前在学校学过一些简单的数据库编程,但现在我正在尝试学习最佳实践,因为我正在编写更复杂的应用程序。写入 MySQL 数据库并不难,但我想知道让分布式应用程序写入 Amazon EC2 上的远程数据库
是否可以写回到ResourceBundle?目前我正在使用 ResourceBundle 来存储信息,在运行时使用以下内容读取信息 while(ResourceBundle.getBundle("bu
关闭。这个问题是not reproducible or was caused by typos .它目前不接受答案。 这个问题是由于错别字或无法再重现的问题引起的。虽然类似的问题可能是on-topi
我是一名优秀的程序员,十分优秀!