内存===文件
从文件到内存为I
从内存到文件为O
man 3 fopen
可以打开linux的操作手册关于fopen的相关资料
同样的
man 3 fwrite
linux自带的读写,使用一次就会读一次或写一次磁盘,效率其实不如c标准库的高
在vscode中,写入FILE,ctrl加左键可以进入他的定义,发现他的原型是_IO_FILE,再次ctrl加左键,发现该结构体中,有char*类型的各个变量用于读写和缓冲
利用MMU(内存管理单元)来进行虚拟内存和物理内存之间的管理和转换
在Linux的内核区,有一个PCB(进程控制块),可以控制文件描述符
文件描述符存储在文件描述符表内,文件描述符表在数据结构上是数组形式,表的默认大小为1024
文件描述符表的前三位是固定的
就是标准输入、标准输出、标准错误,默认是打开状态
/dev/tty 通过上述3位可以找到当前绑定的设备终端
他们对应的终端是同一个
一个文件能被打开多次,但是多次打开的文件描述符是不一样的
在fopen打开一个文件时,一个文件描述符被占用,只有将其fclose或以linux内部的close关闭后,这个文件描述符才能再次启用
内核会自己寻找空闲的最小的文件描述符
int open(const char *pathname,int flags);
int open(const char *pathname,int flags,mode_t mode);
int close(int fd);
ssize_t read(int fd,void *buf,size_t count);
ssize_t write(int fd,const void *buf,size_t count);
off_t lseek(int fd,off_t offset,int whence);
int stat(const char *pathname.struct stat *statbuf);
int lstat(const char *pathname,struct stat *statbuf);
虽然函数重载是c++的内容,但是上述函数是C语言的,所以两个open其实是采用可变参数的方式实现的
open函数的声明在fcntl.h这个头文件内,open内部的flags定义了一些宏,放到另外两个头文件中
第一个open函数用于打开一个已经存在的文件
int open(const char *pathname,int flags);
参数:
返回值:
errno:属于Liux系统函数库,库里面的一个全局变量,记录的是最近的错误号
/*
#include
#include
#include
//打开一个已经存在的文件
int open(const char *pathname, int flags);
参数:
- pathname:要打开的文件路径
- flags:对文件的操作权限及其他设置
O_RDONLY,O_WRONLY,O_RDWR 这三个设置是互斥的
返回值:返回一个新的文件描述符,如果调用失败,返回-1
errno:属于Liux系统函数库,库里面的一个全局变量,记录的是最近的错误号
#include
void perror(const char *s);
s参数:用户描述,比如hello,最终输出的内容是 hello:xxx(实际错误描述)
作用:打印errno对应的错误描述
//创建一个新的文件
int open(const char *pathname, int flags, mode_t mode);
#include
int close(int fd);
*/
#include
#include
#include
#include
#include
int main(){
int fd = open("a.txt",O_RDONLY);
if(fd == -1){
perror("open");
}
//关闭
close(fd);
return 0;
}
第二个open函数用于创建一个新的文件
int open(const char *pathname,int flags,mode_t mode);
参数:
pathname:要打开的文件路径
flags:对文件的操作权限及其他设置
- 必选项:O_RDONLY,O_WRONLY,O_RDWR
- 可选项:O_CREAT 文件不存在创建文件
11111101
按位与:0和任何数都为0
umask的作用就是抹去某些权限
可以用umask 后面跟上数值来修改例如 umask 022
但是这个修改只能作用在本窗口,新开一个窗口就会失效
read:
头文件: #include
ssize_t read(int fd, void *buf, size_t count);
参数:
返回值:
write:
头文件: #include
ssize_t write(int fd, const void *buf, size_t count);
参数:
返回值:
#include
#include
#include
#include
#include
int main()
{
//1.通过open打开english.txt文件
int srcfd = open("english.txt",O_RDONLY);
if(srcfd == -1){
perror("open");
return -1;
}
//2.创建一个新的文件(拷贝文件)
int destfd = open("cpy.txt",O_WRONLY|O_CREAT,0664);
if(destfd == -1){
perror("open");
return -1;
}
//3.频繁的读写操作
char buf[1024] = {0};
int len = 0;
while(( len = read(srcfd,buf,sizeof(buf))) > 0){
write(destfd,buf,len);
}
//4.关闭文件
close(destfd);
close(srcfd);
return 0;
}
标准C库的函数
#include
int fseek(FILE *stream, long offset, int whence);
Linux系统函数
#include
#include
off_t lseek(int fd, off_t offset, int whence);
第一个头文件放了一些宏定义,第二个头文件是unix的标准头文件
参数:
作用:
移动文件指针到头文件
lseek(fd,0,SEEK_SET);
获取当前文件指针的位置
lseek(fd,0,SEEK_CUR);
获取文件长度
lseek(fd,0,SEEK_END);
拓展文件的长度,当前文件10b,110b,增加了100个字节
lseek(fd,100,SEEK_END);
注意:需要写一次数据
#include
#include
#include
#include
#include
int main(){
int fd = open("hello.txt",O_RDWR);
if(fd == -1){
perror("open");
return -1;
}
//扩展文件的长度
int ret = lseek(fd,100,SEEK_END);
if(ret == -1)
{
perror("lseek");
return -1;
}
//写入一个空数据
write(fd," ",1);
//关闭文件
close(fd);
return 0;
}
#include
#include
#include
int stat(const char *pathname, struct stat *statbuf);
作用:获取一个文件相关的一些信息
参数:
返回值:
int lstat(const char *pathname, struct stat *statbuf);
作用:获取软链接文件本身的信息
参数:
#include
#include
#include
#include
int main(){
struct stat statbuf;
int ret = stat("a.txt",&statbuf);
if(ret == -1){
perror("stat");
return -1;
}
printf("size:%ld\n",statbuf.st_size);
return 0;
}
stat a.txt
可以查看a的一些信息
ln -s a.txt b.txt
创建一个软链接文件b.txt指向a.txt
若这里使用stat访问b.txt,则实际访问的是a.txt的信息
若想要访问b.txt本身,则需要lstat