write() 函数进一步认识

1.多个进程同时写一个日志文件会混乱吗?

多个进程写一个文件可能会出现数据覆盖/混乱等情况,但是一个 master 进程和多个 worker 进程(有父子关系)同时写一个日志文件,我们看到输出结果并不混乱,是有序的。

  • O_APPEND 这个标记能够保证多个进程操作同一个文件时不会相互覆盖;

  • 内核 wirte() 写入是原子操作;

  • 父进程和子进程是亲缘关系,共享文件表项。

参考《UNIX环境高级编程第3版》第三章和第八章。

2.write() 函数是否将数据成功写到磁盘?

write() 调用返回时,内核将应用程序缓冲区所提供的数据放到了内核缓冲区,但是无法保证数据已经写出到其预定的目的地(磁盘),所以 wirte() 调用不等价于数据在内核缓冲区和磁盘之间的数据交换。

在这里插入图片描述

在这里插入图片描述

3.掉电导致 write() 的数据丢失的解决方法

(1) 直接I/O

  • open() 文件时用 O_DIRECT 选项,绕过内核缓冲区,直接访问物理磁盘。

在这里插入图片描述

(2) open() 文件时用 O_SYNC 选项

  • O_SYNC 是同步选项,即把数据直接同步到磁盘,只针对 write() 函数有效,使每次 write() 操作等待物理I/O操作的完成。具体来说,就是将写入内核缓冲区的数据立即写入磁盘,将掉电等问题造成的损失减到最小。

在这里插入图片描述

(3) 缓存同步:尽量保证缓存数据和写到磁盘上的数据一致

  • sync(void):将所有修改过的块缓冲区排入写队列,然后返回,并不等待实际写磁盘操作结束,数据是否写入磁盘并没有保证。

  • fsync(int fd):将 fd 对应的文件的块缓冲区立即写入磁盘,并等待实际写磁盘操作结束返回。fsync 会同步更新数据部分和文件属性。

  • fdatasync(int fd):和 fsync 类似,但只影响文件的数据部分。

多次 write(),每次 write() 务必要大块大块地写,每次不要只写几个字节,一般 512 ~ 4k,然后调用一次 fsync()。

4.标准I/O库

fopen, fclose, fread, fwrite, fflush, fseek, fgetc, fputc, fgets, printf, fprintf, sprintf, scanf, fscanf, sscanf …

fwrite() 是标准I/O库,一般在 stdio.h 文件中。

write() 是系统调用,所有系统调用都是原子性的。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值