文件锁/建议锁的由来
当两个进程在同一时刻向同一个文件中写入数据时,
可能造成数据的交错和不一致问题;
当一个进程在向文件写入数据的同时,
另外一个进程读取文件中数据时也可能造成数据的不一致问题;
当两个进程同时读取同一个文件数据时,可以同时进行;
为了实现上述表格的效果,linux系统中引入文件锁的机制,
文件锁本质上就是读写锁,一把读锁和一把写锁,
其中读锁是一把共享锁,允许其他进行加读锁,但不能加写锁;
写锁是一把排他锁,不允许其他进行加读锁/写锁
******************************************************
******************************************************
fcntl函数
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );
第一个参数:文件描述符,一般给open函数的返回值
第二个参数:具体的操作命令 - 主要用于实现建议锁功能
F_SETLK:当锁的类型是F_RDLCK(读锁)或F_WRLCK(写锁)时实现加锁效果;
F_UNLCK(解锁)时,实现解锁效果;
具体的锁信息由该函数的第三个参数指定
***当文件上已经拥有冲突锁时,
该函数调用失败,返回-1并设置errno的数值
F_SETLKW:功能和F_SETLK类似,所不同的是当文件上已经拥有冲突锁信息时;
该函数调用并不会返回失败,而是一直等待下去,直到文件上存在的
锁被释放为止;
F_GETLK:如果该锁能够被放在文件上,则不会真正放置上去;
只是将锁的类型改为F_UNCLK,结构体其他的成员保持不变
如果该锁不能被放置在文件上,则fcntl函数会用文件上
已经存在的锁信息去替换第三个参数描述的锁信息,
并将l_pid的数值设置为真正给文件加锁进程的进程号
实际用途:判断当前文件受否有锁?!并且获取锁的信息
第三个参数:可变长参数,是否需要取决于cmd
当实现建议锁功能时,该参数是一个指向以下结构体的指针,具体的结构体类型如下:
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; /* 加锁的进程号,默认给-1 (F_GETLK only) */
...
};
函数功能:
主要用于对指定的文件描述符执行指定的操作;
返回值:-1,表示加锁失败!1.46
释放锁的主要方式:
1.将锁类型设置为F_UNLCK,使用fcntl函数调用即可;
2.使用close函数关闭文件描述符,与该描述符相关的文件锁全部被自动释放;
3.当进程结束时,与该进程相关的文件锁全部被释放;
******************************************************
******************************************************
******************************************************
#include <unistd.h>
int access(const char *pathname, int mode);
第一个参数:字符串形式的文件路径名
第二个参数:具体操作模式
F_OK:判断文件是否存在
R_OK:判断文件是否可读
W_OK:判断文件是否可写
X_OK:判断文件是否可执行
成功返回0;失败返回-1
函数功能:主要用于检查文件的权限
*********文件管理:*********
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);
第一个参数:字符串类型的文件路径名/文件描述符
第二个参数:结构体指针,传递结构体变量的地址
函数功能:只要用于获取指定文件的状态信息;
成功返回0;失败返回-1
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* 文件的类型和权限 */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* 文件大小,单位:字节 */
blksize_t st_blksize; /* blocksize for file system I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* 最后一次的修改时间 */
time_t st_ctime; /* time of last status change */
};
获取文件大小的方法:
a:调用fseek(),ftell();
b: 调用lseek();
b: 调用stat()/fstat();
#include <time.h>
char *ctime(const time_t *timep);
功能:主要用于将参数指定的整数时间转换成字符串类型时间
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 + 1900 */
int tm_wday; /* day of the week */
int tm_yday; /* day in the year */
int tm_isdst; /* daylight saving time */
};
#include <sys/stat.h>
int chmod(const char *path, mode_t mode);
int fchmod(int fd, mode_t mode);
第一个参数:字符串类型的文件路径名/文件描述符
第二个参数:重新设置的权限;比如:0664
功能:主要用于将指定文件的权限修改为指定的新权限
成功返回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'
成功返回0;失败返回-1
#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
第一个参数:建立映射的起始地址
第二个参赛:建立映射的长度
第三个参赛:映射的访问权限
PROT_EXEC 可执行
PROT_READ 可读
PROT_WRITE 可写
PROT_NONE 不可访问
第四个参赛:具体的操作标志,映射对文件是否有效
第五个参赛:文件描述符,默认0
第六个参数:文件中的偏移量,默认0
返回值:成功返回映射首地址,失败返回 MAP_FAILED
函数功能:
主要用于建立文件/设备到虚拟地址的映射
int munmap(void *addr, size_t length);
第一个参数:映射区的首地址,mmap函数的返回值
第二个参数:映射区的大小
函数功能:
主要用于解除参数指定的映射
主要用于建立/解除 文件/设备 到 虚拟地址的映射;
本质上就是把对文件的读写操作转换为对内存地址的操作,当有大量的数据进行读写操作时,
这种方式效率比read/write函数的方式高些
其他操作函数
umask():设置新文件在创建时要屏蔽的权限
link():创建硬链接
unlink():删除硬链接
rename():实现重命名的效果
remove():删除文件
**********目录的管理*********
opendir函数
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
函数功能: 主要用于打开参数指定的目录,成功返回一个DIR类型的指针,失败返回NULL;
readdir函数
#include <dirent.h>
struct dirent *readdir(DIR *dirp);
函数功能:
主要用于读取参数指定目录中的内容,成功返回一个结构体指针,失败返回NULL;
该函数返回NULL有两种情况:一种是读到了目录的末尾,但是不会改变errno的数值;
另一种是出现了错误,但是会设置errno的数值表达错误的原因;
struct dirent
{
... ...
unsigned char d_type; /* 文件的类型 */
char d_name[256]; /* 文件的名称 */
};
closedir函数
#include <sys/types.h>
#include <dirent.h>
int closedir(DIR *dirp);
函数功能:
主要用于关闭参数指定的目录,参数为opendir函数的返回值;
其他目录操作函数
mkdir() - 主要用于创建目录;
rmdir() - 主要用于删除目录;
chdir() - 主要用于切换目录;
getcwd() - 主要用于获取当前工作目录的绝对路径;
... ...