Linux文件编程——write函数
在 Linux 文件编程中,write
函数是一个系统调用,用于将数据从缓冲区写入文件描述符(file descriptor)指向的文件或设备。它是 Unix/Linux 系统编程中非常重要的底层 I/O 操作之一。以下是 write
函数的详细使用方法和注意事项:
1. 函数原型
#include <unistd.h>ssize_t write(int fd, const void *buf, size_t count);
- 参数:
fd
:文件描述符(File Descriptor),通过open
或creat
等函数获得。buf
:指向要写入数据的缓冲区的指针。count
:要写入的字节数。
- 返回值:
- 成功时返回实际写入的字节数(可能小于
count
)。 - 失败时返回
-1
,并设置errno
表示错误原因。
- 成功时返回实际写入的字节数(可能小于
2. 使用方法
基本示例
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>int main() {int fd;char buf[] = "Hello, Linux!";ssize_t bytes_written;// 打开文件(如果不存在则创建,权限为 rw-r--r--)fd = open("example.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);if (fd == -1) {perror("open failed");return 1;}// 写入数据bytes_written = write(fd, buf, strlen(buf));if (bytes_written == -1) {perror("write failed");close(fd);return 1;}printf("Successfully wrote %zd bytes\n", bytes_written);// 关闭文件close(fd);return 0;
}
关键步骤
- 打开文件:
- 使用
open
函数获取文件描述符,指定写入模式(如O_WRONLY
、O_RDWR
)和创建选项(如O_CREAT
)。 - 设置文件权限(如
0644
表示rw-r--r--
)。
- 使用
- 写入数据:
- 调用
write(fd, buf, count)
,将buf
中的数据写入文件。 - 检查返回值,确保写入成功。
- 调用
- 关闭文件:
- 使用
close(fd)
释放文件描述符。
- 使用
3. 注意事项
(1) 返回值处理
write
可能不会一次性写入所有请求的数据(尤其是写入大文件或慢速设备时)。- 必须检查返回值,并在必要时循环写入剩余数据:
ssize_t total_written = 0;
while (total_written < count) {ssize_t bytes_written = write(fd, buf + total_written, count - total_written);if (bytes_written == -1) {perror("write failed");break;}total_written += bytes_written;
}
(2) 错误处理
- 常见错误包括:
EBADF
:无效的文件描述符。ENOSPC
:磁盘空间不足。EINTR
:被信号中断(需重试)。EIO
:底层 I/O 错误。
- 使用
perror
或strerror(errno)
打印错误信息。
(3) 缓冲与非阻塞 I/O
write
是无缓冲的(直接调用系统调用),但文件可能因缓冲设置(如O_DIRECT
)或设备特性而延迟写入。- 对于非阻塞文件描述符(如套接字),
write
可能返回EAGAIN
或EWOULDBLOCK
,需结合select
/poll
使用。
(4) 性能优化
- 批量写入(减少系统调用次数)。
- 使用
O_DIRECT
绕过内核缓冲(需对齐内存和文件偏移)。 - 对于大文件,考虑
pwrite
进行分散/聚集写入(Scatter-Gather I/O)。
(5) 安全性
- 确保缓冲区
buf
的有效性,避免越界访问。 - 验证文件描述符
fd
的合法性(如通过fstat
检查)。
(6) 信号中断
- 如果
write
被信号中断(EINTR
),通常需要重新尝试写入。
4. 替代函数
pwrite
:在指定偏移量处写入(无需lseek
)。writev
:分散写入(从多个缓冲区写入数据)。sendfile
:零拷贝文件传输(适用于网络或进程间通信)。
5. 总结
write
是 Linux 文件编程的基础函数,使用时需注意:
- 正确处理返回值和错误。
- 确保数据完整写入(循环写入)。
- 结合文件打开模式和权限设置。
- 考虑性能和安全性优化。
通过合理使用 write
,可以高效、可靠地完成文件 I/O 操作。