标准C库函数 和 Linxu系统IO函数 open和close 虚拟地址空间
C库的IO函数
C库函数通过 FILE指针 来访问文件并索引到对应磁盘文件,
FILE文件指针(结构体)
文件描述符:定位文件
文件读写指针:对数据进行操作 读写指针
缓冲区:提高效率
FILE 是 _IO_FILE 的重定义
1 struct _IO_FILE 2 { 3 int _flags; /* High-order word is _IO_MAGIC; rest is flags. */ 4 5 /* The following pointers correspond to the C++ streambuf protocol. */ 6 char *_IO_read_ptr; /* Current read pointer */ //读指针 7 char *_IO_read_end; /* End of get area. */ 8 char *_IO_read_base; /* Start of putback+get area. */ 9 char *_IO_write_base; /* Start of put area. */ 10 char *_IO_write_ptr; /* Current put pointer. */ //写指针 11 char *_IO_write_end; /* End of put area. */ 12 char *_IO_buf_base; /* Start of reserve area. */ //缓冲区起始 13 char *_IO_buf_end; /* End of reserve area. */ //缓冲区结束 14 15 /* The following fields are used to support backing up and undo. */ 16 char *_IO_save_base; /* Pointer to start of non-current get area. */ 17 char *_IO_backup_base; /* Pointer to first valid character of backup area */ 18 char *_IO_save_end; /* Pointer to end of non-current get area. */ 19 20 struct _IO_marker *_markers; 21 22 struct _IO_FILE *_chain; 23 24 int _fileno;//文件描述符 标准C库的IO函数调用会调用Linux系统的IO函数,系统IO函数会返回一个文件描述符fd标识,标准C库得到fd赋给 _fileno 通过fd文件描述符的值获取文件位置 25 int _flags2; 26 __off_t _old_offset; /* This used to be _offset but it's too small. */ 27 28 /* 1+column number of pbase(); 0 is unknown. */ 29 unsigned short _cur_column; 30 signed char _vtable_offset; 31 char _shortbuf[1]; 32 33 _IO_lock_t *_lock; 34 #ifdef _IO_USE_OLD_IO_FILE 35 };
标准 C 库 IO 和 Linux 系统 IO 的关系
虚拟地址空间 :解决程序加载内存的问题,解决堆、栈的问题。
虚拟地址空间是不存在的,是虚拟的想象中的空间, 32位开辟的虚拟地址空间一般位2^32(4GB) 64位开辟的虚拟地址空间一般位2^48。
以4G为例:最多为4G但是理想状态,实际用不到4G,堆空间为 低地址向高地址存储, 栈空间为高地址往低地址存储,
内核区:用户无读写权限,想要操作内核数据,需要进行系统调用,调用Linux系统的API函数
文件描述符
程序:不占用内存空间,仅占用磁盘空间。
进程(正在运行的程序):操作系统创建,给运行的程序分配的一些资源,占用内存空间,启动后有虚拟地址空间,通过CPU中MMU逻辑管理单元,将虚拟地址空间中数据映射到物理内存中。
文件描述符:在进程的内核区,(Linux内核就是一个程序,PCB进程控制块是一个复杂的结构体),结构体中有一个数组,即文件描述符表(文件描述符表,表中每个文件描述符都对应一个文件),默认大小为1024,同时能打开的最多文件数为1024个。
文件描述符表:前三位默认占用:标准输入,标准输出,标准错误,且默认打开,对应于当前使用的终端。
open函数和close函数
1 /* 2 #include <sys/types.h> 3 #include <sys/stat.h> 4 #include <fcntl.h> 5 //多个头文件 是因为open函数中多个参数在不同头文件中,调用的时候按需使用 6 //打开一个存在的文件 7 int open(const char* pathname, int flags); 8 参数: 9 - pathname:要打开的文件路径 10 - flags:对文件的操作权限设置还有其他的设置 11 O_RDONLY, O_WRONLY, O_RDWR 这三个设置是互斥的 12 返回值: 返回一个新的文件描述符,如果调用失败,返回 -1 13 14 errno:属于Linux系统函数库,库里面的一个全局变量,记录的是最近的错误号 15 #include <stdio.h> 16 void perror(const char* s) 17 作用:打印errno对应的错误描述 18 s参数:用户描述,比如hello,最终输出的内容是 hello:xxx(实际的错误描述) 19 20 //创建一个新的文件 21 int open(const char* pathname, int flags,mode_t mode); 22 */ 23 #include <sys/types.h> 24 #include <sys/stat.h> 25 #include <fcntl.h> 26 #include <stdio.h> //perror函数 27 #include <unistd.h> //close函数 28 int main() 29 { 30 int fd = open("a.txt",O_RDONLY);//fd文件描述符:file descriptor 31 if(fd == -1) 32 { 33 perror("open");//打印 open:具体错误原因 34 //open:No such file or directory 35 } 36 //关闭 37 close(fd); 38 return 0; 39 }
未创建 a.txt 文件前,输出错误
rwx三个一组: 当前文件权限,所在组文件权限,其他文件权限
r:读取 w:写 x:可执行权限
umask:0002(普通用户)(不同用户的umask值不同) root用户(0022)
umask 022 将umask设置为 0022(仅在当前终端有效)
例如:设置权限最高为0777(八进制) 但是根据 最终的权限: mode & ~umask 普通用户的设定umask为(0002) 结果为0775 其他文件权限降低
1 /* 2 #include <sys/types.h> 3 #include <sys/stat.h> 4 #include <fcntl.h> 5 6 //创建一个新的文件 7 int open(const char* pathname, int flags,mode_t mode); 8 参数: 9 - pathname:要创建的文件路径 10 - flags:对文件的操作权限和其他设置 11 - 必选项: O_RDONLY, O_WRONLY, O_RDWR 互斥 三选一 12 - 可选项: O_CREAT 文件不存在,创建新文件 13 - mode:八进制的数,表示创建出新文件的操作权限 14 最终的权限是: mode & ~umask 15 umask:0002(普通用户)(不同用户的umask值不同) root用户(0022) 16 0002取反(~umask) 0775 17 0777(111 111 111) & 0775(111 111 101) 18 按位与(0与任何书都为0)---> 111111101 0775 19 umask作用就是抹去 某些权限 20 21 int fd = open("create.txt",O_RDWR | O_CREAT,0777); 为什么用 | (按位或) 22 flags参数是一个 int类型的数据 占4个字节, 32位 23 flags 32个位,每一个就是一个标志位 24 第几位: 1--R 2--W 3--RW 4--CREATE 25 */ 26 #include <sys/types.h> 27 #include <sys/stat.h> 28 #include <fcntl.h> 29 #include <stdio.h> //perror函数 30 #include <unistd.h> //close函数 31 32 int main() 33 { 34 //创建一个新的文件 35 int fd = open("create.txt",O_RDWR | O_CREAT,0777);//键入0777 由于普通用户umask 结果为0775 36 37 if(fd == -1) 38 { 39 perror("open"); 40 } 41 //关闭 42 close(fd); 43 return 0; 44 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)