LinuxI/O高级函数 | 小牛学习日记
LinuxI/O高级函数
Published in:2025-02-20 | category: C++
Words: 2.4k | Reading time: 8min | reading:

linux 高级I/O函数

1、open

用于打开或创建文件、设备文件等。

1
2
3
4
5
6
#include <fcntl.h>

// 用于打开已存在的文件
int open(const char *pathname, int flags);
// 用于打开或创建文件,当需要创建文件时使用
int open(const char *pathname, int flags, mode_t mode);

pathname:这是一个字符串指针,指向要打开或创建的文件的路径名。可以是绝对路径(如 /home/user/test.txt),也可以是相对路径(如 test.txt)。
flags:这是一个整数,用于指定打开文件的方式和一些额外的选项。常用的标志位如下:
O_RDONLY:以只读模式打开文件。
O_WRONLY:以只写模式打开文件。
O_RDWR:以读写模式打开文件。
O_CREAT:如果文件不存在,则创建该文件。使用此标志时,需要同时提供第三个参数 mode 来指定文件的权限。
O_EXCL:与 O_CREAT 一起使用时,如果文件已经存在,则 open 函数会失败并返回 -1,可用于确保创建一个新文件。
O_TRUNC:如果文件存在且以写模式打开,则将文件截断为长度为 0。
O_APPEND:以追加模式打开文件,每次写操作都会将数据追加到文件末尾。
mode:当使用 O_CREAT 标志时,需要提供此参数来指定新创建文件的权限。mode 是一个八进制数,通常使用 umask 来屏蔽一些权限位。例如,0644 表示文件所有者具有读写权限,而组用户和其他用户具有只读权限。

2、read/write

用于执行文件 I/O(输入 / 输出)操作的基础函数,它们可以对文件、设备等进行数据的读取和写入。

1
2
3
#include <unistd.h>

ssize_t read(int fd, void *buf, size_t count);

fd:这是一个文件描述符,代表要读取数据的文件、设备等。文件描述符通常是通过 open、socket 等函数返回得到的。
buf:这是一个指向缓冲区的指针,用于存储从文件中读取的数据。读取的数据会被存储到这个缓冲区中。
count:这是一个 size_t 类型的整数,表示要读取的最大字节数。

返回值
正数:表示实际成功读取的字节数。
0:表示已经到达文件末尾,没有更多数据可供读取。
-1:表示读取操作失败,此时 errno 会被设置为具体的错误码,可以通过 perror 或 strerror 函数来获取错误信息。

3、lseek

用于移动文件读写指针的位置。

1
2
3
4
#include <sys/types.h>
#include <unistd.h>

off_t lseek(int fd, off_t offset, int whence);

fd:文件描述符,代表要操作的文件。这个文件描述符通常是通过 open 函数打开文件后返回得到的。
offset:偏移量,它是一个 off_t 类型的整数,用于指定从 whence 参数所指定的位置开始移动的字节数。可以是正数(表示向文件末尾方向移动)、负数(表示向文件开头方向移动)或 0。
whence:指定偏移量的起始位置,它有以下三种取值:
SEEK_SET:从文件的开头开始计算偏移量,即 offset 是相对于文件开头的字节数。
SEEK_CUR:从文件的当前读写位置开始计算偏移量,offset 是相对于当前位置的字节数。
SEEK_END:从文件的末尾开始计算偏移量,offset 是相对于文件末尾的字节数,通常 offset 取负数表示向文件开头方向移动。

返回值
成功:返回从文件开头到新的文件读写指针位置的字节数,类型为 off_t。
失败:返回 -1,并设置 errno 变量来指示具体的错误原因。常见的错误包括无效的文件描述符、不支持随机访问的设备等。

4、stat/lstat

用于获取文件或文件系统对象的状态信息,例如文件的权限、大小、创建时间、修改时间等。不过,它们在处理符号链接时有一些差异。

stat

1
2
3
4
5
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int stat(const char *pathname, struct stat *buf);

pathname:一个指向字符串的指针,代表要获取状态信息的文件或目录的路径名。可以是绝对路径(如 /home/user/test.txt),也可以是相对路径(如 test.txt)。
buf:一个指向 struct stat 结构体的指针,用于存储获取到的文件状态信息。

struct stat 结构体定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct stat {
dev_t st_dev; /* 文件所在设备的 ID */
ino_t st_ino; /* 文件的 inode 编号 */
mode_t st_mode; /* 文件的类型和权限 */
nlink_t st_nlink; /* 硬链接的数量 */
uid_t st_uid; /* 文件所有者的用户 ID */
gid_t st_gid; /* 文件所有者的组 ID */
dev_t st_rdev; /* 设备文件的设备 ID */
off_t st_size; /* 文件的大小(字节) */
blksize_t st_blksize; /* 文件系统的块大小 */
blkcnt_t st_blocks; /* 文件占用的块数 */
time_t st_atime; /* 最后访问时间 */
time_t st_mtime; /* 最后修改时间 */
time_t st_ctime; /* 最后状态改变时间 */
};

返回值
成功:返回 0。
失败:返回 -1,并设置 errno 变量来指示具体的错误原因,例如文件不存在、权限不足等。

lstat

1
2
3
4
5
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int lstat(const char *pathname, struct stat *buf);

与 stat 函数的参数相同,pathname 是要获取状态信息的文件或目录的路径名,buf 是用于存储文件状态信息的 struct stat 结构体指针。

区别
当 pathname 是一个符号链接时,lstat 函数不会跟随符号链接,而是返回符号链接本身的状态信息。这意味着 lstat 函数可以用来判断一个文件是否为符号链接,因为符号链接的 st_mode 字段会有特定的标志位。

如果你需要获取符号链接所指向的目标文件的状态信息,应该使用 stat 函数。
如果你需要获取符号链接本身的状态信息,或者判断一个文件是否为符号链接,应该使用 lstat 函数。

5、pipe

主要用于在进程间进行通信,创建的管道是一种半双工的通信机制,即数据只能在一个方向上流动

1
2
3
#include<unistd.h>

int pipe(int fd[2]);

pipefd是一个包含两个整数的数组,用于存储管道的文件描述符。具体如下:
pipefd[0]:表示管道的读端文件描述符,进程可以通过这个文件描述符从管道中读取数据。
pipefd[1]:表示管道的写端文件描述符,进程可以通过这个文件描述符向管道中写入数据。

返回值
成功:返回 0,并且 pipefd 数组会被正确填充为管道的读端和写端文件描述符。
失败:返回 -1,并设置 errno 变量来指示具体的错误原因,常见的错误包括 EMFILE(当前进程已经打开了太多的文件描述符)、ENFILE(系统范围内的文件描述符已经用尽)等。

6、dup/dup2

dup

用于复制现有的文件描述符。

1
2
3
#include <unistd.h>

int dup(int oldfd);

oldfd:需要被复制的现有文件描述符。
返回值
成功:返回一个新的文件描述符,这个新的文件描述符与 oldfd 指向同一个文件表项。
失败:返回 -1,并设置 errno 变量来指示具体的错误原因,例如 EBADF 表示 oldfd 不是一个有效的文件描述符。

dup2

dup2 函数同样用于复制文件描述符,但它允许用户指定新的文件描述符的值。

1
2
3
#include <unistd.h>

int dup2(int oldfd, int newfd);

oldfd:需要被复制的现有文件描述符。
newfd:指定的新文件描述符的值。

返回值
成功:返回新的文件描述符(即 newfd)。
失败:返回 -1,并设置 errno 变量来指示具体的错误原因,例如 EBADF 表示 oldfd 或 newfd 不是有效的文件描述符。

7、fcntl

用于对已打开的文件描述符进行各种控制操作,比如改变文件的访问模式、获取或设置文件状态标志等。

1
2
3
#include <fcntl.h>

int fcntl(int fd, int cmd, ... /* arg */ );

fd:需要进行操作的文件描述符,通常是通过 open、pipe、socket 等函数返回得到的。
cmd:指定要执行的操作命令,不同的命令会有不同的功能,并且可能需要额外的参数。常见的命令有以下几类:
复制文件描述符:F_DUPFD、F_DUPFD_CLOEXEC。
获取 / 设置文件状态标志:F_GETFL、F_SETFL。
获取 / 设置文件锁:F_GETLK、F_SETLK、F_SETLKW。
获取 / 设置文件描述符标志:F_GETFD、F_SETFD。
:这是一个可变参数,根据 cmd 的不同,可能需要提供额外的参数。例如,当 cmd 为 F_DUPFD 时,需要提供一个整数作为新文件描述符的最小值;当 cmd 为 F_SETFL 时,需要提供一个整数表示要设置的文件状态标志。

返回值
成功:返回值取决于具体的 cmd。例如,当 cmd 为 F_DUPFD 时,返回一个新的文件描述符;当 cmd 为 F_GETFL 时,返回文件的状态标志。
失败:返回 -1,并设置 errno 变量来指示具体的错误原因,常见的错误包括 EBADF(无效的文件描述符)、EINVAL(无效的 cmd 命令)等。

Next:
文件属性与目录操作函数
Prev:
C++静态库和动态库的区别