文件类型
- 普通文件(文本文件和二进制文件)
- 目录文件
- 字符设备文件
- 块设备文件
- 链接文件
- 套接字文件,用户网络通信
- 管道文件,用户进程间通信
文件相关函数
- stat()
#include <sys/types.h> #include <sys/stat.h> #include <unistd.h> int stat(const char *pathname, struct stat *buf); //stat结构体原型 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; /* 设备号(指针对设备文件) */ off_t st_size; /* 文件大小(以字节为单位) */ blksize_t st_blksize; /* 文件内容存储的块大小 */ blkcnt_t st_blocks; /* 文件内容所占块数 */ struct timespec st_atim; /* 文件最后被访问的时间 */ struct timespec st_mtim; /* 文件内容最后被修改的时间 */ struct timespec st_ctim; /* 文件状态最后被改变的时间 */ }; //结构体timespec原型 struct timespec { time_t tv_sec; /* 秒 */ syscall_slong_t tv_nsec; /* 纳秒 */ };
根据结构体stat的st_mode字段判断文件类型
- 方法一,通过文件类型字段位掩码
/* 判断是不是普通文件 */ if ((st.st_mode & S_IFMT) == S_IFREG) { /* 是 */ } /* 判断是不是链接文件 */ if ((st.st_mode & S_IFMT) == S_IFLNK) { /* 是 */ }
方法二,通过宏定义
S_ISREG(m) #判断是不是普通文件,如果是返回 true,否则返回 false S_ISDIR(m) #判断是不是目录,如果是返回 true,否则返回 false S_ISCHR(m) #判断是不是字符设备文件,如果是返回 true,否则返回 false S_ISBLK(m) #判断是不是块设备文件,如果是返回 true,否则返回 false S_ISFIFO(m) #判断是不是管道文件,如果是返回 true,否则返回 false S_ISLNK(m) #判断是不是链接文件,如果是返回 true,否则返回 false S_ISSOCK(m) #判断是不是套接字文件,如果是返回 true,否则返回 false
fstat(), 和stats不同的是,该函数是通过文件描述符获得文件属性结构体
#include <sys/types.h> #include <sys/stat.h> #include <unistd.h> int fstat(int fd, struct stat *buf);
lstat(), lstat()与 stat、fstat 的区别在于,对于符号链接文件,stat、fstat 查阅的是符号链接文件所指向的文件对应的文件属性信息,而 lstat 查阅的是符号链接文件本身的属性信息。
#include <sys/types.h> #include <sys/stat.h> #include <unistd.h> int lstat(const char *pathname, struct stat *buf);
chown(), 修改文件所有者和文件所属组
- 只有超级用户进程能更改文件的用户 ID;
- 普通用户进程可以将文件的组 ID 修改为其所从属的任意附属组 ID,前提条件是该进程的有效用
户 ID 等于文件的用户 ID;而超级用户进程可以将文件的组 ID 修改为任意值;
#include<unistd.h> // 该函数只有超级用户进程能更改文件的用户id, int chown(const char *pathname, uid_t owner, gid_t group); // 传入的是ID,不是其名字,eg: 传入0, 而不是root
- fchown()和lchown()函数与chown()函数的区别和前面说的stat(),fstat(), lstat()区别类似。
- getuid(), getgid(), 获取当前进程的用户ID,用户组ID
#include <unistd.h> #include <sys/types.h> uid_t getuid(void); gid_t getgid(void);
access(), 检查当前执行该程序的用户是否具有某种权限
#include <unistd.h> int access(const char *pathname, int mode); // 通过返回0, 否则返回-1
mode(可使用|连接多个进行判断):
- F_OK: 是否存在
- R_OK: 是否具有读的权限
- W_OK: 是否具有写的权限
- X_OK: 是否具有执行的权限
- chmod(), 修改文件权限
#include <sys/stat.h> int chmod(const char *pathname, mode_t mode); int fchmod(int fd, mode_t mode);
umask(), 修改权限掩码(每个进程都有一个独立的权限掩码,继承于父线程)
#include <sys/types.h> #include <sys/stat.h> mode_t umask(mode_t mask); // 返回的是原来的掩码
link(), 创建硬链接
#include <unistd.h> int link(const char *oldpath, const char *newpath);
symlink(), 创建软链接
#include <unistd.h> int symlink(const char *target, const char *linkpath);
unlink(), 删除文件(不包括目录), unlink()系统调用并不会对软链接进行解引用操作,若 pathname 指定的文件为软链接文件,则删除软链接文件本身,而非软链接所指定的文件
#include <unistd.h> int unlink(const char *pathname);
remove(), 移除文件或空目录
#include <stdio.h> int remove(const char *pathname);
rename(), 既可以对文件进行重命名,又可以将文件移至同一文件系统中的另一个目录下
#include <stdio.h> int rename(const char *oldpath, const char *newpath);
目录相关
- mkdir(), 建立目录
#include <sys/stat.h> #include <sys/types.h> int mkdir(const char *pathname, mode_t mode);
rmdir(),删除空目录
#include <unistd.h> int rmdir(const char *pathname); int remove(const char *pathname); // 也只能删除空目录
opendir(), 打开目录, 以及下面的readdir(), closedir() 其实是和文件读写类似的。
#include <sys/types.h> #include <dirent.h> DIR *opendir(const char *name);
readdir(), 读取目录中的一个目录条目,其指针也会自动移动(类似read函数),目录读取结束会返回NULL, 读取发生错误也会返回NULL,这样的话就不能区分了,我们可以给用前面提到的errno来判断(发生错误该变量会变成非0值)(<errno.h>)
#include <dirent.h> struct dirent *readdir(DIR *dirp); // dirent结构体原型, 注意: 有的系统支持d_ino和d_name struct dirent { ino_t d_ino; /* inode 编号 */ off_t d_off; /* not an offset; see NOTES */ unsigned short d_reclen; /* length of this record */ unsigned char d_type; /* type of file; not supported by all filesystem types */ char d_name[256]; /* 文件名 */ };
losedir(), 关闭目录
#include <sys/types.h> #include <dirent.h> int closedir(DIR *dirp);
getcwd(), 获取当前工作目录
#include <unistd.h> char *getcwd(char *buf, size_t buff_size);
chdir(), 修改当前工作目录
#include <unistd.h> int chdir(const char *path); int fchdir(int fd);
符号链接(软链接)和硬链接
- 符号链接:符号链接是一个独立的文件,他有自己的inode, 其文件内容就是一个路径。源文件如果删除了该链接就会变成一个死链接
#include <unistd.h> // 软链接文件不能使用open函数读取,他会去读取到他所链接的文件 ssize_t readlink(const char *pathname, char *buf, size_t buf_size);
- 硬链接: 硬链接没有自己的inode, 每个硬链接共用同一个inode。struct stat结构体中的st_nlink成员变量记录了该文件的链接数。源文件如果删除了,该链接任然存在。