回忆
一、lseek(2) 重新定位读写文件的位置
二、使用mmap将文件映射到进程的虚拟地址空间
在内存中对数据的更改直接反应到文件中
三、文件描述符的复制
dup (2)
dup2(2)
文件描述符的具体概念
文件输出重定向
文件输入重定向
四、获取文件的元数据
inode i节点 每个文件都有自己的inode 且是唯一的
硬链接 软链接 原理
stat(2) struct stat结构体
uid gid 时间的处理 ctime
根据uid 和gid找到用户名字和用户组名字
结构体 成员 值-结果参数
权限的问题
文件类型
今天的内容:
一 获取文件的元数据(文件类型和权限)
-rw-rw-r-- 1 nan nan 615 1月 10 10:25 笔记
第一个字符代表文件的类型
- 普通文件
d 文件夹
c 字符设备文件
b 块设备文件
l 软连接文件
s socket文件
p 管道文件
rw-rw-r--
属主owner 属组 other
40775
170000
111
4
二 文件夹的操作
427171 drwxrwxr-x 2 nan nan 4096 1月 10 11:34 hello
rwx
x 可通过
r w 文件夹的内容是什么
文件夹的内容就是文件夹里的文件或者文件夹
如何才算对文件夹的内容进行写操作
删除文件 新建文件
使用函数对文件夹里的内容进行读操作(遍历)
opendir(3)
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
功能:打开一个文件夹
参数:
name:指定了文件夹的名字
返回值:返回一个指向文件夹流的指针,指向文件夹下的第一个条目
错误时返回NULL errno被设置
closedir(3)
#include <sys/types.h>
#include <dirent.h>
int closedir(DIR *dirp);
功能:关闭文件夹
参数:
dirp 指定要关闭的文件夹流
返回值:成功返回0
错误 -1 errno被设置
readdir(3)
#include <dirent.h>
struct dirent *readdir(DIR *dirp);
功能:从文件夹读取一个文件夹条目
参数
dirp 指定了文件夹流
返回值:成功返回指向结构体的指针
返回NULL 到达了文件夹的末尾或者错误
如果是错误 errno被设置
struct dirent {
ino_t d_ino; /* inode number */
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]; /* filename */
};
cJSON
docker容器
三 文件锁的使用
两种 读锁(共享锁) 写锁(互斥锁)
锁的实现又分为两种 建议锁 强制锁
如何使用文件锁
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );
功能:
参数:
fd 指定了要操作的文件操作符
cmd
F_SETLK 设置一把锁 加锁,如果有互斥锁,立即返回-1, errno被设置
F_SETLKW 设置一把锁,加锁 如果有互斥锁 等待这把锁被释放
F_GETLK 测试是否可以放置锁 如果返回的lock的l_type里是F_UNLOCK,说明可以放置锁。如果有其他进程已经放置互斥锁,返回持有该互斥锁的进程的pid到lock的l_pid字段里
... 可变参数 参数的个数 类型 取决于cmd
返回值:成功 0
错误 -1 errno被设置
struct flock {
...
short l_type; /* Type of lock: F_RDLCK,
F_WRLCK, F_UNLCK */
short l_whence; /* How to interpret l_start:
SEEK_SET, SEEK_CUR, SEEK_END */
off_t l_start; /* Starting offset for lock */
off_t l_len; /* Number of bytes to lock */
pid_t l_pid; /* PID of process blocking our lock
(set by F_GETLK and F_OFD_GETLK) */
...
};
编写代码如下 pa.c 完成对指定文件加读锁
pb.c完成对指定文件加写锁
pc.c测试文件是否可以加读锁
四 库函数和系统调用的关系
fopen(3) fclose(3) fputc(3) fgetc(3)
open read write close
演示代码 file.c
fopen(3)首先为FILE类型的变量分配空间,然后分配一块用于文件操作的缓冲区。将缓冲区中的相应地址记录到FILE类型的变量空间的字段里。调用open,返回文件描述符,记录在fileno中。
fgetc(3) 从参数中找到读取数据的缓冲区,从中读取数据,如果空间里有数据,立即返回,如果没有数据,调用read(2)从文件中读取数据到缓冲区,然后,fgetc获取到数据,立即返回。
fputc(3)从参数中找到存放数据的缓冲区,如果有足够的空间,将数据放入缓冲区,立即返回,如果缓冲区空间不足,调用write(2)将缓冲的数据写入到文件,清空缓冲区,fputc将数据放入到缓冲然后返回
fclose(3)首先将缓冲区中的数据同步到文件中,释放缓冲区,调用close(2)关闭文件描述符fileno。释放FILE类型变量的空间。
库函数封装了系统调用
缓冲文件,非缓冲文件
库函数的效率比较高,可以跨操作系统。
五 文件操作的杂项
access(2)
getcwd(3)
chdir(2)
mkdir(2)
rmdir(2)
basename(3)
dirname(3)
link(2)硬链接
unlink(2)
chmod(2)
rename(2)
remove(3)
symlink(2)
t_ls.c
#include<t_stdio.h>
#include<t_file.h>
#include<dirent.h>
int main(int argc,char* argv[]){
//打开文件夹
DIR *dir=opendir(".");
if(!dir) E_MSG("open",-1);
while(1){
struct dirent *p=readdir(dir);
if(!p)break;
if(p->d_name=="."||p->d_name=="..")
continue;
printf("%s ",p->d_name);
}
printf("\n");
closedir(dir);
return 0;
}
stat.c
#include<t_stdio.h>
#include<t_file.h>
#include<time.h>
#include<pwd.h>
#include<grp.h>
int main(int argc,char *argv[]){
//获取文件的元数据,存储到buf
struct stat buf;
int s=stat(argv[1],&buf);
if(s==-1) E_MSG("stat",-1);
printf("hard links:%u\n",buf.st_nlink);
printf("size:%ld\n",buf.st_size);
printf("inode:%ld\n",buf.st_ino);
printf("mtime:%s",ctime(&buf.st_mtime));
printf("uid:%u\n",buf.st_uid);
printf("username:%s\n",(getpwuid(buf.st_uid))->pw_name);
printf("gid:%u\n",buf.st_gid);
printf("group grname:%s\n",(getgrgid(buf.st_gid))->gr_name);
printf("mode:%o\n",buf.st_mode);
switch(buf.st_mode&S_IFMT){
case S_IFDIR:
printf("d");
break;
case S_IFREG:
printf("-");
break;
default:
break;
}
(buf.st_mode&S_IRUSR)?printf("r"):printf("-");
(buf.st_mode&S_IWUSR)?printf("w"):printf("-");
(buf.st_mode&S_IXUSR)?printf("x"):printf("-");
(buf.st_mode&S_IRGRP)?printf("r"):printf("-");
(buf.st_mode&S_IWGRP)?printf("w"):printf("-");
(buf.st_mode&S_IXGRP)?printf("x"):printf("-");
(buf.st_mode&S_IROTH)?printf("r"):printf("-");
(buf.st_mode&S_IWOTH)?printf("w"):printf("-");
(buf.st_mode&S_IXOTH)?printf("x"):printf("-");
printf("\n");
return 0;
}
pa.c
#include<t_stdio.h>
#include<t_file.h>
#include<fcntl.h>
int main(int argc,char* argv[]){
//给指定文件加读锁 argv【1】传递
int fd=open(argv[1],O_RDONLY|O_CREAT);
if(fd==-1) E_MSG("OPEN",-1);
struct flock lock;
//初始化lock
lock.l_type=F_RDLCK;
lock.l_whence=SEEK_SET;
lock.l_start=0;
lock.l_len=6;
int f=fcntl(fd,F_SETLK,&lock);
if(f==-1) E_MSG("fcntl",-1);
printf("read lock...\n");
//加写锁
lock.l_type=F_WRLCK;
lock.l_whence=SEEK_SET;
lock.l_start=0;
lock.l_len=6;
fd=open(argv[1],O_WRONLY|O_CREAT);
f=fcntl(fd,F_SETLK,&lock);
if(f==-1) E_MSG("fcntl",-1);
printf("write lock...\n");
getchar();//保证当前进程不关闭,锁不消失
//关闭文件描述符时,所有记录锁就没了
close(fd);
return 0;
}
pb.c
#include<t_stdio.h>
#include<t_file.h>
#include<fcntl.h>
int main(int argc,char* argv[]){
//给指定文件加读锁 argv【1】传递
int fd=open(argv[1],O_WRONLY|O_CREAT);
if(fd==-1) E_MSG("OPEN",-1);
struct flock lock;
//初始化lock
lock.l_type=F_WRLCK;
lock.l_whence=SEEK_SET;
lock.l_start=0;
lock.l_len=6;
int f=fcntl(fd,F_SETLK,&lock);
if(f==-1) E_MSG("fcntl",-1);
printf("WRITE lock...\n");
getchar();//保证当前进程不关闭,锁不消失
//关闭文件描述符时,所有记录锁就没了
if(f==-1) E_MSG("fcntl",-1);
close(fd);
return 0;
}
pc.c
#include<t_stdio.h>
#include<t_file.h>
#include<fcntl.h>
int main(int argc,char* argv[]){
//给指定文件加读锁 argv【1】传递
int fd=open(argv[1],O_RDONLY|O_CREAT);
if(fd==-1) E_MSG("OPEN",-1);
struct flock lock;
//初始化lock
lock.l_type=F_RDLCK;
lock.l_whence=SEEK_SET;
lock.l_start=0;
lock.l_len=6;
int f=fcntl(fd,F_GETLK,&lock);
if(f==-1) E_MSG("fcntl",-1);
if(lock.l_type==F_UNLCK)
printf("may read lock\n");
else
printf("block proccess pid is%d\n",lock.l_pid);
//关闭文件描述符时,所有记录锁就没了
if(f==-1) E_MSG("fcntl",-1);
close(fd);
return 0;
}
file.c
#include<t_stdio.h>
int main(int argc,char*argv[]){
FILE *fp=fopen(argv[1],"r");
if(fp==NULL) E_MSG("open",-1);
fclose(fp);
return 0;
}
dir.c
#include<t_stdio.h>
#include<t_file.h>
#include<dirent.h>
int main(int argc,char* argv[]){
//打开文件夹
DIR *dir=opendir(argv[1]);
if(!dir) E_MSG("open",-1);
printf("open dir success...\n");
//关闭文件夹
while(1){
struct dirent *p=readdir(dir);
if(!p)break;
printf("file:%s\t inode:%lu\n",p->d_name,p->d_ino);
}
closedir(dir);
return 0;
}