磁盘的写入
1、硬盘上一般都会有一些缓冲区一次来提高数据的写入效率,操作系统写入数据其实只是写入缓冲区,直到缓冲区满,才排队写入磁盘中。
2、这种操作降低了写入的次数,但是提高了数据写入的延时,导致缓冲区中的数据与磁盘中的内容不同步。
#include <unistd.h>
void sync(void);
功能:把所有缓冲区中的数据全部同步到磁盘。
注意:只是发布将数据同步到磁盘的命令,并不等待执行完毕才返回,而是命令发布后立即返回。
void fsync(int fd);
功能:指定fd文件的缓冲区数据同步到磁盘,只针对一个文件,数据同步到磁盘后才返回。
void fdatasync(int fd);
功能:指定fd文件的缓冲区数据同步到磁盘,但仅是文件的数据并不同步文件属性
fcntl函数有关文件的操作
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd,int cmd,....);
注意:这是变长参数的函数
fd:文件描述符
cmd:操作指令,不同的操作指令决定后续参数的个数和类型
1、复制文件描述符,与fd操作同一个文件
int fcntl(int fd,int cmd,long newfd);
cmd:F_DUPFD
功能:复制文件描述符,与fd操作同一个文件
返回值:如果newfd没有使用,则返回newfd,如果newfd已经被占用,则返回一个不小于newfd的文件描述符。
2、设置或获取文件描述符标志
int fcntl(int fd,int cmd,void/long);
cmd:
F_GETFD(void),返回值:0新进程保持打开状态,1新进程中关闭该文件描述符
F_SETFD(long),目前只能设置FD_CLOEXEC标志位,返回值:成功返回0失败返回-1。
3、获取文件状态标志,指的是此文件打开的权限以及打开方式
int fcntl(int fd, int cmd, void/long);
cmd:
F_GETFL (void)
O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC 不能获取
返回值:带有文件状态标志的int类型变量,需要与各标志相与得到
F_SETFL (long)
O_APPEND, O_ASYNC,O_DIRECT, O_NOATIME, and O_NONBLOCK 只能设置
返回值:成功返回0失败返回-1。
4、为文件加锁,能锁整个文件,或者锁一部分,一旦进程结束,锁会自动解锁
int fcntl(int fd,int cmd,struct* flock);
cmd:
F_GETLK 获取锁的信息
F_SETLK 设置文件锁
F_SETLKW 测试锁,测试是否被加锁
注意:加锁并不能让其他进程打不开文件或不能操作,而是使用者都要遵守锁的约定,确保文件不混乱(劝谏锁)。
struct flock {
...
short l_type; /* 锁的类型 */
short l_whence; /* 基础位置 How to interpret l_start:
SEEK_SET, SEEK_CUR, SEEK_END */
off_t l_start; /* 偏移值 */
off_t l_len; /* 锁的长度为0表示锁到文件尾 */
pid_t l_pid; /* 加锁的进程号 */
...
};
读锁与写锁 成功
读锁与写锁 失败
写锁与写锁 失败
获取文件相关属性
#include <sys/stat.h>
功能:用来获取文件属性,返回值:成功返回0失败-1
int stat(const char *path,struct stat *buf);
path:文件路径
int fstat(int fd,struct stat *buf);
fd:需要打开后的文件描述符
int lstat(const char *path,struct stat *buf);
stat/fstat会跟踪链接目标,而lstat不跟踪链接目标
struct stat{
dev_t st_dev; /* 设备ID */
ino_t st_ino; /* 节点号 */
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; /* IO块数 */
blkcnt_t st_blocks; /* 占用块(512字节)数 */
time_t st_atime; /* 最后访问时间 */
time_t st_mtime; /* 最后修改时间 */
time_t st_ctime; /* 最后文件属性修改时间 */
};
st_mode:
S_ISREG(m) 测试是否是标准文件
S_ISDIR(m) 目录
S_ISCHR(m) 字符设备文件
S_ISBLK(m) 块设备文件
S_ISFIFO(m) 管道设备文件
S_ISLNK(m) 链接文件
S_ISSOCK(m) socket文件
S_IFMT 0170000 获取文件类型出错
S_IFSOCK 0140000 socket文件
S_IFLNK 0120000 软链接文件
S_IFREG 0100000 标准文件
S_IFBLK 0060000 块设备文件
S_IFDIR 0040000 目录
S_IFCHR 0020000 字符设备文件
S_IFIFO 0010000 管道文件
S_ISUID 0004000 设置UID字节位
S_ISGID 0002000 set-group-ID bit (see below)
S_ISVTX 0001000 设置粘滞位,不能随便删除
S_IRWXU 00700 属主的读写执行权限
S_IRUSR 00400 owner has read permission
S_IWUSR 00200 owner has write permission
S_IXUSR 00100 owner has execute permission
S_IRWXG 00070 同组的读写执行权限
S_IRGRP 00040 group has read permission
S_IWGRP 00020 group has write permission
S_IXGRP 00010 group has execute permission
S_IRWXO 00007 其他用户的读写执行权限
S_IROTH 00004 others have read permission
S_IWOTH 00002 others have write permission
S_IXOTH 00001 others have execute permission
#include <time.h>
struct tm *localtime(const time_t *timep);
功能:使用一个记录秒数据的变量,获取当前时间
struct tm {
int tm_sec; /* seconds */
int tm_min; /* minutes */
int tm_hour; /* hours */
int tm_mday; /* day of the month */
int tm_mon; /* month */
int tm_year; /* year */
int tm_wday; /* day of the week */
int tm_yday; /* day in the year */
int tm_isdst; /* daylight saving time */
};
文件的访问权限
#include <unistd.h>
int access(const char *pathname,int mode);
功能:测试当前用户对文件的访问权限,或者文件是否存在
pathname:文件路径
mode:
F_OK 是否存在
R_OK 是否有读权限
W_OK 是否有写权限
X_OK 是否有执行权限
返回值:成功返回0失败返回-1
#include <sys/types.h>
#include <sys/stat.h>
mode_t umask(mode_t mask);
功能:设置并获取权限屏蔽码,功能与umask命令一样,一旦设置成功,新创建文件就不会具有mask中的权限
返回值:旧的权限屏蔽码
注意:该权限屏蔽码只对当前进程有效,进程结束后返回默认值
#include<sys/stat.h>
int chmod(const char *path,mode_t mode);
int fchmod(int fd,mode_t mode);
功能:修改文件的权限,返回值:成功返回0失败返回-1
注意:它们不受权限屏蔽码的干扰
修改文件的大小
#include <unistd.h>
#include <sys/types.h>
int truncate(const char *path,off_t length);
int ftruncate(int fd,off_t length);
功能:修改文件的大小
返回值:成功返回0失败返回-1
文件的链接操作
1、硬链接
#include <unistd.h>
int link(const char *oldpath,const char *newpath);
功能:创建硬链接文件,硬链接指向的是文件的内容,因此当链接目标被删除后依然可以访问文件的内容。
int unlink(const char *pathname);
功能:删除硬链接文件
注意:普通文件就是硬链接数位1的文件,当把一个文件的硬链接数删除到0个时,这个文件就被删除了。
int remove(const char *pathname);
功能:删除文件,该函数是标准库中的删除文件函数,底层调用了unlink系统调用。
int rename(const char *oldpath,const char *newpath);
功能:文件重命名
2、软链接
#include <unistd.h>
int symlink(const char *oldpath, const char *newpath);
功能:创建软链接(目录文件只能创建软链接)
oldpath:链接目标
newpath:链接文件
返回值:成功返回0失败返回-1。
ssize_t readlink(const char *path, char *buf, size_t bufsiz);
功能:读取软链接文件的内容而非链接目标(open打开软链接文件是打开的是目标文件)
path:链接文件的路径
buf:读取数据的存储位置
bufsiz:读取多少个字节
返回值:成功读取的字节数。
目录操作
#include <sys/stat.h>
#include <sys/types.h>
int mkdir(const char *pathname, mode_t mode);
功能:创建目录,目录一定要有执行权限,否则无法打开
返回值:成功返回0失败返回-1
#include <unistd.h>
int rmdir(const char *pathname);
功能:删除空目录
返回值:成功返回0失败返回-1
#include <unistd.h>
char *getcwd(char *buf,size_t size);
功能:获取当前进程的工作目录,工作目录是指当不加路径信息时,创建/打开时从那个目录下查找,工作目录。
默认是程序所在目录。
int chdir(const char *path);
功能:修改进程的工作目录
返回值:成功返回0失败返回-1。
int fchdir(int fd);
功能:修改进程的工作目录
fd:被open打开的目录文件的fd
返回值:成功返回0失败返回-1。
目录流操作
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
功能:打开一个目录流
返回值:目录流(链表)
DIR *fdopendir(int fd);
功能:使用文件描述符获取目录流,fd必须是目录文件的。
struct dirent *readdir(DIR *dirp);
功能:从目录流中读取一个文件结点信息
struct dirent {
ino_t d_ino; /* 结点号 */
off_t d_off; /* 下一个文件结点信息的偏移量 */
unsigned short d_reclen; /* 当前记录的长度 */
unsigned char d_type; /* 文件类型 */ %hhu
char d_name[256]; /* 文件名 */
};
DT_BLK This is a block device.
DT_CHR This is a character device.
DT_DIR This is a directory. 4
DT_FIFO This is a named pipe (FIFO).
DT_LNK This is a symbolic link.
DT_REG This is a regular file. 8
DT_SOCK This is a UNIX domain socket.
DT_UNKNOWN The file type is unknown.
void rewinddir(DIR *dirp);
功能:把文件目录流指针调整到开头位置
long telldir(DIR *dirp);
功能:获取当前目录流的位置指针在第几个文件结点
void seekdir(DIR *dirp, long offset);
功能:调整当前目录流的位置指针
offset:根据开头位置指针,进行偏移
要和telldir函数配合使用
int closedir(DIR *dirp);