dup和dup2
int dup(int oldfd);
功能:复制文件描述符
oldfd:已经打开了的文件描述符
返回值:系统随机返回一个新的文件描述述newfd,但与oldfd代表同一个内核对象。
当对oldfd和newfd进行读写时,访问的是同一个文件。
int dup2(int oldfd, int newfd);
功能:按指定的newfd复制文件描述符
如果newfd已经被占用,则把它关闭重新复制。
在记录软件的日志经常使用(非常好用),能解决复杂的问题。
返回值:成功返回0,失败返回-1。
fcntl
int fcntl(int fd, int cmd, ... /* arg */ );
功能:
1、复制文件描述符
2、获取或追加文件状态标志
3、添加或获取文件锁
fd: 被操作的文件描述符
cmd:
F_DUPFD 复制文件描述符,返回一个没有使用过的最小的一个文件描述符。
F_GETFD 获取文件状态标志
F_SETFD 追加文件状态标志
O_RDONLY,O_WRONLY, O_RDWR,O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC无法设置。
仅支持O_APPEND, O_ASYNC, O_DIRECT,O_NOATIME, and O_NONBLOCK。
F_SETLK 设置锁的状态为 F_RDLCK、F_WRLCK、F_UNLCK, 成功返回0,失败返回-1。
F_SETLKW 设置锁的状态为 F_RDLCK、F_WRLCK、F_UNLCK,成功返回0,如果无法加锁,则一直等待,除非被信号打断。
F_GETLK 设置测试锁,如果可以设置则设置,如果不能设置则返回返回锁的状态。
文件锁是让多个程序同时和平访问一个的的方法。
struct flock {
short l_type; 锁的类型F_RDLCK,F_WRLCK, F_UNLCK
short l_whence; 加锁内存的基础位置SEEK_SET, SEEK_CUR, SEEK_END
off_t l_start; 偏移植
off_t l_len; 锁的长度
pid_t l_pid; 加锁的进程
};
读锁 读锁 Ok
读锁 写锁 NO
写锁 写锁 NO
Linux系统默认的是劝谏锁(协议),防君子不能防小人。
添加锁的三种方式:
F_SETLK 直接加,成功或失败
F_SETLKW 不成功则一直等待直到成功
F_GETLK 加测试锁
文件同步
1、大多数磁盘的IO都通过缓冲进行了,写入文件其实是写入缓冲区,直到缓冲区(此缓冲区不是标准C的缓冲区)满才排除写入磁盘。
2、缓冲区机制降低了写操作的次数,提高了写作效率,但可能 导致磁盘文件与缓冲区数据不同步。
3、sync/fsync/fdatasync用于强制把缓冲区的数据同步到磁盘中。
void sync(void);
sync是把所有缓冲区的数据排队写入磁盘,不等待完成就直接返回了。
int fsync(int fd);
fsync只针对一个文件,直致缓冲区中的数据全部写入磁盘才返回。
int fdatasync(int fd);
fdatasync只同步文件的数据,不同步属性。
获取文件属性
int stat(const char *path, struct stat *buf);
功能:根据文件的路径来获取文件的属性
int fstat(int fd, struct stat *buf);
功能:根据文件描述符来获取文件的属性
int lstat(const char *path, struct stat *buf);
功能:获取链文件的属性
struct stat {
dev_t st_dev; 文件的设备ID
ino_t st_ino; 文件的节点号
mode_t st_mode; 文件的类型和权限
nlink_t st_nlink; 硬链接数量
uid_t st_uid; 属主ID(文件的拥有者的用户ID)
gid_t st_gid; 属组ID(文件的拥有者的用户组ID)
dev_t st_rdev; 特殊设备ID
off_t st_size; 文件的总字节数
blksize_t st_blksize; I/O块数
blkcnt_t st_blocks; 以512字节为一块,占多少块
time_t st_atime; 最后访问时间
time_t st_mtime; 最后的修改时间
time_t st_ctime; 最后状态修改时间
};
st_mode
S_IFSOCK 套接字文件
S_IFLNK 软链接文件
S_IFREG 普通文件
S_IFBLK 块设备文件
S_IFDIR 目录
S_IFCHR 字符设备文件
S_IFIFO 管道文件
S_ISUID 属主沾滞位标志(一般合并在执行权限上)
S_ISGID 属组沾滞位标志
S_ISVTX 其它沾滞位标志
S_IRWXU 属主的读写执行权限
S_IRUSR 属主的读权限
S_IWUSR 属主的写权限
S_IXUSR 属主的执行权限
S_IRWXG 属组的读写执行权限
S_IRGRP 属组的读权限
S_IWGRP 属组的写权限
S_IXGRP 属组的执行权限
S_IRWXO 其它的读写执行权限
S_IROTH 其它的读权限
S_IWOTH 其它的写权限
S_IXOTH 其它的执行权限
帮助判断文件类型的宏函数:
S_ISREG(m) 普通文件 -
S_ISDIR(m) 目录文件 d
S_ISCHR(m) 字符设备文件 c
S_ISBLK(m) 块设备文件 b
S_ISFIFO(m) 管道文件 p
S_ISLNK(m) 软链接文件 l
S_ISSOCK(m) 套接字文件 s
struct passwd *getpwuid(uid_t uid);
功能:根据用户ID获取用户信息
struct group *getgrgid(gid_t gid);
功能:根据组ID获取组信息
测试文件权限
int access(const char *pathname, int mode);
功能:测试文件是否具有某个权限
pathname:文件和路径
mode:被测试的权限
F_OK 文件是否存在
R_OK 文件是否有读权限
W_OK 文件是否有写权限
X_OK 文件是否有执行权限
返回值:有则返回0,没有则返回-1
权限屏蔽码
当创建文件时设置文件的权限会被权限屏蔽码过滤一下。
mode_t umask(mode_t mask);
功能:为当前进程设置权限屏蔽码,并返回之前的权限屏蔽码,该函数永远成功。
注意:一旦设置完成,当前进行所创建的文件都不具有权限屏蔽码所包括的权限,只对当前进程有效。
注意:chmod命令不受权限屏蔽码的影响。
修改文件的权限
int chmod(const char *path, mode_t mode);
功能:根据文件的路径修改文件的权限
int fchmod(int fd, mode_t mode);
功能:根据文件描述符修改文件的权限
chmod函数和命令都不受权限屏蔽码的影响。
修改文件的大小
int truncate(const char *path, off_t length);
功能:根据文件的路径修改文件的大小
返回值:成功返回0,失败返回-1
int ftruncate(int fd, off_t length);
功能:根据文件描述符修改文件的大小
返回值:成功返回0,失败返回-1
注意:从大往小改,丢弃末尾的数据,从小往大改补0。
创建硬链接删除硬链接
int link(const char *oldpath, const char *newpath);
功能:创建硬链接文件
返回值:成功返回0,失败返回-1
int unlink(const char *pathname);
功能:删除链接硬文件
返回值:成功返回0,失败返回-1
注意:普通文件就是硬链接数为1的文件,因此unlink也可能用于删除普通文件。
文件的删除与重命名
int remove(const char *pathname);
功能:删除文件
返回值:成功返回0,失败返回-1
int rename(const char *oldpath, const char *newpath);
功能:重命名文件
返回值:成功返回0,失败返回-1
remove与unlink的区别是什么?
remove与unlink在删除普通文件时没有任何区别。
但remove可以删除目录(空目录),unlink不行。
软链接文件
int symlink(const char *oldpath, const char *newpath);
功能:创建软链接文件
ssize_t readlink(const char *path, char *buf, size_t
bufsiz);
功能:读取软链接文件本身的内容,使用open打开软链接文件打开的是链接目标,而不是软链接文件本身。
返回值:成功读取到的字节数
注意:硬链接就是个文件名,就是目录表中的一个条目,软链接是一个独立的文件,内容是链接目标的路径信息。
目录文件
int mkdir(const char *pathname, mode_t mode);
功能:创建目录
pathname:目录的路径
mode:目录的权限,必须要有执行权限,否则无法进入。
返回值:成功返回0,失败返回-1
int rmdir(const char *pathname);
功能:删除目录,只能删除空目录
返回值:成功返回0,失败返回-1
注意:rmdir与remove的区别是,remove既可以删除普通文件也可以删除空目录,而rmdir只能删除空目录。
工作目录
就是可以不加路径直接使用文件名就可以操作当前目录下的文件,一般默认程序运行时所在的目录就是工作目录。
char *getcwd(char *buf, size_t size);
功能:获取当前工作目录
buf:存储工作目录的路径
size:buf的容量
int chdir(const char *path);
功能:修改当前工作目录,只针对当前进程有效,类似cd命令。
int fchdir(int fd);
功能:根据文件描述符修改当前的工作目录,该描述符对应的必须是目录文件。
目录流
对目录流的操作就是读取目录下的每个条目,以及调整目录流的位置指针,是专门对目录文件的操作。
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
功能:根据路径打开目录文件
返回值:目录流(相当于链表)
DIR *fdopendir(int fd);
功能:根据目录文件的描述符获取目录流
struct dirent *readdir(DIR *dirp);
功能:从目录流中读取一个条目
条目信息包括:
struct dirent {
ino_t d_ino; i节点号
off_t d_off; 下一个条目的偏移量
unsigned short d_reclen; 条目的长度
unsigned char d_type; 文件的类型
char d_name[256]; 文件名
}
文件类型:
DT_BLK 块设备文件
DT_CHR 字符设备文件
DT_DIR 目录文件
DT_FIFO 管道文件
DT_LNK 链接文件
DT_REG 普通文件
DT_SOCK 套接字文件
DT_UNKNOWN 未知类型
void rewinddir(DIR *dirp);
功能:把目录流的位置指针调整到开头。
long telldir(DIR *dirp);
功能:返回当前目录流的位置指针指向了第几个条目
void seekdir(DIR *dirp, long offset);
功能:设置目录流的位置指针