Linux 常用的 C 语言文件 API

First Post:

Last Update:

chdir

1
2
#include<unistd.h>
int chdir(const char* path);

更改当前的工作目录。

path

要切换到的目录路径。

返回值

成功返回 0,失败返回 -1,错误原因存于 errno

chmod

1
2
#include<sys/stat.h>
int chmod(const char* path, mode_t mode);

修改文件的权限。

path

要修改的文件路径字符串。

mode

指定目标权限。如果要传入非宏字面值,使用八进制数,如 0777

常用权限宏:
S_IRUSR: 所有者具有读取权限。
S_IWUSR: 所有者具有写入权限。
S_IXUSR: 所有者具有执行权限。
S_IRGRP: 组具有读取权限。
S_IWGRP: 组具有写入权限。
S_IXGRP: 组具有执行权限。
S_IROTH: 其他用户具有读取权限。
S_IWOTH: 其他用户具有写入权限。
S_IXOTH: 其他用户具有执行权限。

如果要设置多个权限,使用按位或运算符,如 S_IRUSR | S_IXUSR

返回值

成功返回 0,失败返回 -1,错误原因存于 errno

只有该文件的所有者或用户识别码为 0 的用户(root)可以修改文件权限。
出于安全考虑,欲将数据写入一可执行文件,而该文件具有 S_ISUIDS_ISGID 权限(即尝试修改一个以 root 权限执行的程序),这两个位会被清除。
如果一个目录具有 S_ISUID 权限,表示在此目录下只有文件所有者或 root 可以删除文件。

close

1
2
#include<unistd.h>
int close(int fd);

关闭文件。

fd

要关闭的文件描述符。

文件描述符

Linux 系统将所有设备都当作文件来处理,而 Linux 用文件描述符来标识每个文件对象。 文件描述符是一个非负整数,用于唯一标识计算机操作系统中打开的文件。它描述了数据资源,以及如何访问该资源。

POSIX 定义了 STDIN_FILENOSTDOUT_FILENOSTDERR_FILENO 来代表标准输入(Standard input)、标准输出(Standard output)、标准错误(Standard error)。 这三个符号常量的定义位于头文件 unistd.h
习惯上,标准输入的文件描述符是 0,标准输出是 1,标准错误是 2

返回值

成功返回 0,失败返回 -1,错误原因存于 errno

creat

1
2
#include<fcntl.h>
int create(const char* pathname, mode_t mode);

创建一个文件。

pathname

要创建的文件路径字符串。

mode

指定目标权限

返回值

若成功则返回一个最小可用的文件描述符,若有错误则返回 -1,错误原因存于 errno

fcntl

1
2
3
4
#include<fcntl.h>
int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, long arg);
int fcntl(int fd, int cmd, struct flock* lock);

改变一个已打开文件的访问模式(即 flags)。

fd

要更改设置的文件描述符

cmd

操作类型。

F_GETFL: 读取访问模式和锁信息。
F_SETFL: 设置访问模式和锁信息。
F_GETOWN: 获取绑定了 SIGIO 信号的目标进程号。
F_SETOWN: 绑定 SIGIO 信号的目标进程。

以下操作的作用有疑问:
F_DUPFD: 返回一个如下描述的文件描述符:

  1. 最小的大于或等于 arg 的一个可用的描述符;
  2. 与原始操作符一样的某对象的引用;
  3. 如果对象是文件(file)的话,该描述符与 arg 共享相同的偏移量(offset);
  4. 相同的访问模式(读,写或读/写);
  5. 相同的文件状态标志(如:两个文件描述符共享相同的状态标志);
  6. 与新的文件描述符结合在一起的 close-on-exec 标志被设置成交叉式访问 execve(2) 的系统调用。

F_GETFD: 取得与文件描述符 fd 联合 close-on-exec 标志,类似 FD_CLOEXEC。如果返回值和 FD_CLOEXEC 进行与运算结果是 0 的话,文件保持交叉式访问 exec(),否则如果通过 exec 运行的话,文件将被关闭(arg 被忽略)。
F_SETFD: 设置 close-on-exec 旗标。该旗标以参数 arg 的 FD_CLOEXEC 位决定。

arg

操作对应的参数。
可以有多种含义,如新的访问模式,或是绑定 SIGIO 信号的目标进程号。

lock

记录文件锁具体状态的 flock 结构体。

flock 结构体

1
2
3
4
5
6
7
8
struct flock
{
short l_type;
short l_whence;
off_t l_start;
off_t l_len;
pid_t l_pid;
};

l_type

加锁的类型。

F_WRLCK: 有读取锁;
F_WRLCK: 有写入锁;
F_UNLCK: 未加锁。

l_whence

l_start 的解释。

SEEK_SET: 从文件开头算起;
SEEK_CUR: 从当前位置算起;
SEEK_END: 从文件末尾算起。

l_start

指明加锁部分的开始位置。

l_len

指明加锁的长度。

l_pid

施加锁的进程的进程号。

返回值

与命令有关。
如果出错,所有命令都返回 -1 且错误原因存于 errno
如果成功则返回 0 或某个其他值。下列三个命令有特定返回值:F_DUPFDF_GETFL 以及 F_GETOWN。第一个返回新的文件描述符,第二个返回相应标志,最后一个返回一个正的进程 ID 或负的进程组 ID。

flock

1
2
#include<sys/file.h>
int flock(int fd, int operation);

锁定文件或解除锁定(用于加建议性锁)。

fd

要锁定或解锁的文件描述符

operation

要进行的操作。

LOCK_SH: 建立共享锁定。多个进程可以同时对同一个文件做共享锁定。
LOCK_EX: 建立互斥锁定。一个文件同时只能有一个互斥锁定。
LOCK_UN: 解除文件锁定。
LOCK_NB: 如果指定此参数,函数不能获得文件锁就立即返回,否则,函数会等待获得文件锁。

返回值

成功返回 0,失败返回 -1,错误原因存于 errno

单一文件无法同时建立共享锁和互斥锁,而当使用 dup()fork() 时不会继承此种锁定。

fstat

stat。但 fstat 接受一个文件描述符作为参数,而不是文件路径。

link

1
2
#include<unistd.h>
int link(const char* oldpath, const char* newpath);

以参数 newpath 指定的名称来建立一个新的硬连接到参数 oldpath 所指定的已存在文件。如果参数 newpath 指定的名称为一已存在的文件则不会建立连接。

oldpath

要连接到的已有文件路径字符串。

newpath

要建立的连接路径字符串。

返回值

成功返回 0,失败返回 -1,错误原因存于 errno

硬连接无法跨越不同文件系统,如果需要请改用 symlink

lstat

stat。但当文件是一个符号链接时,lstat 获取该符号链接本身的信息,而 stat 获取链接指向的文件的信息。

mkdir

1
2
#include<sys/stat.h>
int mkdir(const char* path, mode_t mode);

创建目录。

注意:一次只能创建一个目录。如果要创建的目录的父目录不存在,则会创建失败。

path

要创建的目录的路径。

mode

指定目标权限。如果要传入非宏字面值,使用八进制数,如 0777

返回值

成功返回 0,失败返回 -1,错误原因存于 errno

open

1
2
3
#include<fcntl.h>
int open(const char* pathname, int flags);
int open(const char* pathname, int flags, mode_t mode);

打开或创建文件。

pathname

要打开或创建的文件路径字符串。

flags

指定访问文件的模式。

O_RDONLY: 以只读模式打开。
O_WRONLY: 以只写模式打开。
O_RDWR: 以读写模式打开。
O_APPEND: 以追加模式打开,在文件尾写入数据。
O_TRUNG: 设置文件的长度为 0,并舍弃现有的数据。
O_CREAT: 建立文件,可使用 mode 参数设置访问权限。
O_EXCL: 与 O_CREAT 一起使用,若要建立的文件已存在,则打开失败。
O_NONBLOCK: 指定使用非阻塞模式打开。以 read 为例,如果设备暂时没有数据可读,就返回 -1 而不是等待数据,同时置 errnoEWOULDBLOCK,表示本来应该阻塞但实际上并没有阻塞。
O_ASYNC: 指定使用异步方式读取。当输入缓存中的输入数据就绪时(输入数据可读),内核向用 fcntlF_SETOWN 来绑定的那个进程发送 SIGIO 信号。
O_DIRECT: 指定使用无缓冲 IO,即数据 IO 不会经过 OS Cache。
O_NOATIME: 不记录时间戳,例如最近读取或修改时间。
如果要同时使用多个模式 ,使用按位或运算符,如 O_WRONLY | O_CREAT

mode

指定创建文件时的目标权限。如果要传入非宏字面值,使用八进制数,如 0777

返回值

若成功则返回一个最小可用的文件描述符,若有错误则返回 -1,错误原因存于 errno

read

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

从文件读取数据。

fd

要读取的文件描述符

buf

指向要存入数据内容的内存空间的指针。

count

要读取的字节数。

返回值

若成功则返回实际读取到的字节数,若有错误则返回 -1,错误原因存于 errno

若返回的字节数比要求读取的字节数少,则可能读到了文件尾或是从管道、终端读取。

stat

1
2
#include<unistd.h>
int stat(const char* file_name, struct stat* buf);

获取文件属性。

file_name

要获取属性的文件路径字符串。

buf

指向一个 stat 结构体的指针,获取到的文件信息将会存入该结构体中。

stat 结构体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<sys/stat.h>
struct stat
{
dev_t st_dev;
ino_t st_ino;
mode_t st_mode;
nlink_t st_nlink;
uid_t st_uid;
gid_t st_gid;
dev_t st_rdev;
off_t st_size;
unsigned long st_blksize;
unsigned long st_blocks;
time_t st_atime;
time_t st_mtime;
time_t st_ctime;
};

保存文件相关信息。

st_dev

文件所在设备的 ID。

st_ino

索引节点号。

st_mode

文件的保护模式。

可以使用 st_mode 属性和几个宏判断文件类型:
S_ISLNK(st_mode): 是否是一个链接
S_ISREG(st_mode): 是否是一个常规文件
S_ISDIR(st_mode): 是否是一个目录
S_ISCHR(st_mode): 是否是一个字符设备
S_ISBLK(st_mode): 是否是一个块设备
S_ISFIFO(st_mode): 是否是一个 FIFO 文件
S_ISSOCK(st_mode): 是否是一个 Socket 文件

文件的连接数(硬连接)。

st_uid

文件所属用户的用户 ID。

st_gid

文件所属组的组 ID。

st_rdev

设备号(针对设备文件)。

st_size

文件字节数。

st_blksize

系统块的大小。

st_blocks

文件所占系统块数。

st_atime

最后一次访问时间。

st_mtime

最后一次修改时间。

st_ctime

文件属性的最后一次改变时间。

较新的系统中用 st_atimst_mtimst_ctim 取代 st_atimest_mtimest_ctime,用于获取更精确的时间。原有的三个属性被定义成了宏,所以它们可以正常使用。

1
2
3
struct timespec st_atim;
struct timespec st_mtim;
struct timespec st_ctim;

timespec 结构体是 C11 标准中新增的,包含了精确到纳秒的时间戳。它定义在 time.h 中:

1
2
3
4
5
struct timespec
{
time_t tv_sec;
long tv_nsec;
};

tv_sec: 一般的精确到秒的时间戳
tv_nsec: 精确到纳秒的时间戳

返回值

成功返回 0,失败返回 -1,错误原因存于 errno

symlink

1
2
#include<unistd.h>
int symlink(const char* oldpath, const char* newpath);

以参数 newpath 指定的名称来建立一个新的软连接(符号连接)到参数 oldpath 所指定的已存在文件。参数 oldpath 指定的文件不一定要存在。如果参数 newpath 指定的名称为一已存在的文件则不会建立连接。

oldpath

要连接到的已有文件路径字符串。

newpath

要建立的连接路径字符串。

返回值

成功返回 0,失败返回 -1,错误原因存于 errno

umask

1
2
#include<sys/stat.h>
mode_t umask(mode_t mask);

设置建立新文件时使用的权限掩码。

mask

要设置的新权限掩码。使用八进制数,如 0666

返回值

系统原先的权限掩码。

unlink

1
2
#include<unistd.h>
int unlink(const char* pathname);

删除参数 pathname 指定的文件。如果该文件名为最后连接点,但有其他进程打开了此文件,则在所有关于此文件的文件描述词皆关闭后才会删除。如果参数 pathname 为一符号连接,则此连接会被删除。

pathname

要删除的文件路径字符串。

返回值

成功返回 0,失败返回 -1,错误原因存于 errno

write

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

向文件写入数据。

fd

要写入的文件描述符

buf

指向要写入数据内容的内存空间的指针。

count

要写入的字节数。

返回值

若成功则返回实际写入的字节数,若有错误则返回 -1,错误原因存于 errno