美文网首页
File I/O read() and write()

File I/O read() and write()

作者: 无无吴 | 来源:发表于2019-08-06 09:47 被阅读0次

通过read()来读取

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t len);

读取成功,返回写入BUF的字节数。
读取失败,返回-1并且设置errno。
如果fd表示的对象无法查找(例如,字符设备文件),则读取总是发生在“当前”位置。

返回值

read()返回一个比len小的正数是合法的。
read()还可能返回0。它只是表示文件位置已经超过了文件中的最后一个有效偏移量,因此没有其他可读取的内容。
在从套接字或设备文件读取的情况下, 对len字节进行读取,但是没有字节可用于读取,调用将阻塞(睡眠),直到有字节读到为止。
有些错误是可以恢复的。例如,如果对read()的调用在读取任何字节之前被信号中断,它将返回−1(0可能与EOF混淆),并将errno设置为EINTR。在这种i情况下,可以并且应该重新提交所读的内容。
调用返回−1,并将errno设置为EAGAIN。这表示由于当前没有可用的数据,因此读取将阻塞,请求应在稍后重新发出。这只发生在非阻塞模式。

读取所有的字节

int readAllBytes(int fd, char* buf, size_t len)
{
    if(len > SSIZE_MAX){
        len = SSIZE_MAX;
    }
    ssize_t ret = 0;
    while(len != 0 && (ret = read(fd, buf, len)) != 0){
        if(ret == -1){
            if(errno == EINTR){
                continue;
            }
            perror("read");
            break;
        }
        len -= ret;
        buf += ret;
    }
}

非阻塞读取

int readNonBlocking(int fd, char* buf, size_t len)
{
    if(len > SSIZE_MAX){
        len = SSIZE_MAX;
    }
    ssize_t nr;
    start:
    nr = read(fd, buf, len);
    if( nr == -1){
        if(errno == EINTR){
            goto start;
        }
        if(errno == EAGAIN){
            /*resubmit later and do something else first*/
        }
        else{
            perror("read");
        }
    }
}

如果读取len的值为0,那么read()调用会立即返回0.

通过write()来写入

#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);

由不支持查找的对象(例如字符设备)支持的文件总是从“头”开始写。

正确的调用write的方式:

int writeAllBytes(int fd, char *buf, size_t len) {
    ssize_t ret, nr;
    while(len != 0 && (ret = write(fd, buf, len)) != 0){
        if(ret == -1){
            if(errno == EINTR){
                continue;
            }
            perror("write");
            break;
        }
        len -= ret;
        buf += ret;
    }
}

在附加模式下(通过O_APPEND)打开fd时,不会在文件描述符的当前文件位置进行写入。相反,它们发生在文件的当前结尾。

Append Mode

Append Mode避免了此问题。它确保文件位置始终设置为文件的末尾,因此所有写操作都要附加,即使有多个写入器。你可以把它看作是 对每个写入请求之前的文件位置进行原子更新。然后,文件位置被更新到新写入数据的结尾的点。这将不会影响下一次写入的调用,因为它自动更新文件位置,但下一次调用read()可能会有一些奇怪的原因。

Append Mode模式对某些任务(如前面提到的日志文件编写)有很多意义,但对其他任务几乎没有意义。

非阻塞write()

当FD以非阻塞模式打开(通过O_NONBLOCK),并且发出的写入通常会阻塞时,写()系统调用返回−1并将errno设置为EAGAIN。请求应在以后重新发布。通常,这不会出现在常规文件中。

write的写入大小限制

小于SSIZE_MAX,不然结果是未定义的

即使应用程序可能认为写入已经成功,但在系统崩溃的情况下,数据将永远无法到达磁盘。

相关文章

网友评论

      本文标题:File I/O read() and write()

      本文链接:https://www.haomeiwen.com/subject/jumbdctx.html