文章目录
一.C语言中的文件接口
1.fopen
path:带有路径的文件名称(如果不带路径,打开的文件默认是在当前路径下)
mode:打开文件的方式
r :只读方式打开;文件流指向文件起始位置
r+ :可读写方式打开;文件流指向文件起始位置
w :文件存在:则截断(清空文件内容)文件;文件不存在,则创建一个新文件;
w+ :可读可写的方式打开。文件存在:则截断(清空文件内容)文件;文件不存在,则创建一个新文件;
a:追加写。当前文件不存在,则创建文件;当前文件存在,则将文件流指针指向文件末尾进行写。
a +:可以读,也可以追加写。如果文件不存在,则创建文件;读的位置被初始化到文件的头;但是追加写的时候,从文件的末尾开始追加写
返回值:
成功:返回文件流指针 FILE*
失败:返回NULL;
2.fread
ptr:将从文件中读到的内容保存到ptr指向的内存空间中(空间需要合法,即要申请空间)
size:定义从文件读的时候,一个块是多大,单位字节(通常定义为一字节)
nmemb:期望读多少块
stream:文件流指针
返回值:
返回成功读入的文件块的个数
3.fwrite
参数:
ptr:往文件内写的内容
size:定义往文件中写的时候,一个块是多大,单位字节(通常定义为一字节)
nmemb:期望写多少块
stream:文件流指针
返回值:
返回成功写入到文件块的个数
4.fseek
作用:移动文件流指针的位置
参数:
stream:文件流指针
offset:偏移量
whence:将文件流指针偏移到什么位置
SEEK_SET:文件头部
SEEK_CUR:当前文件流指针的位置
SEEK_END:文件末尾
返回值:
成功:0;
失败 :-1;
5.fclose
stream:文件流指针
关闭文件流(关闭文件)
二.系统调用的文件接口
1.open
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
参数:
pathname:要打开或创建的目标文件
flags:打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行“或”运算。构成flags
O_RDONLY:只读打开
O_WRONLY:只写打开
O_RDWR:读,写打开
(这三个选项必须指定一个且只能指定一个)
O_CREAT:若文件不存在,则创建它。此时需要mode选项,来指定新文件的访问权限
O_APPEND:追加写
mode:当创建新文件时,指定创建文件的权限:传递一个八进制数字(例:0664)
返回值:
成功:新打开的文件描述符
失败:-1;
2.read
ssize_t read(int fd, void *buf ,size_t count);
参数:
fd:文件描述符
buf:将buf指向的内容写到文件当中去
count:期望写多少字节
返回值:返回写入字节的数量
3.write
ssize_t write(int fd, const void *buf ,size_t count);
参数:
fd:文件描述符
buf:将从文件中读到的内容写到buf指向的空间中去(需要提前开辟空间)
count:期望读多少字节
返回值:返回读到字节的数量
4.lseek
off_t lseek (int fd, off_t offset,int whence);
参数:
fd:文件描述符
offset:偏移量,单位字节
whence:偏移的位置
SEEK_SET:文件头部
SEEK_CUR:当前文件流指针的位置
SEEK_END:文件末尾
返回值:
成功:返回偏移量的位置,单位字节
失败:-1;
5.close
int close(int fd);
关闭文件描述符
三.文件描述符
是一个正数,没有负数
可以在/proc/[进程号]/fd
文件夹下查看,对应的就是它的文件描述符
0,1,2对应的物理设备一般是:键盘,显示器,显示器
1. 文件描述符分配规则
最小未使用原则
2. 从内核理解文件描述符
struct task_struct
文件描述符在内核当中本质上就是task_struct结构体中的一个结构体指针files所指向的结构体struct files_struct中的结构体指针数组fd_array的数组下标
一个进程最多打开多少个文件描述符
解答:
1.系统当中针对一个进程打开的文件描述符的数量是有限的
2.通过ulimit -a可以查看“open files”的大小,而“open files”的大小就是限制一个进程可以打开的文件描述符的数量
3.我的机器中看到的“openfiles”的大小是100001,也就是意味着我的机器创建出来的进程最大可以打开的文件数量是100001
4.open fiels”的大小并不是没有办法改变。可以通过 ulinit -n [数字] 进行改变 e.g:ulimit -n 10000
就是将一个进程打开文件描述符的数量改为了10000
四.重定向
1 重定向的符号
> :清空重定向
> >:追加重定向
2 重定向的接口
int dup2(int oldfd,int newfd);
作用:将newfd的值重定向为oldfd,即newfd拷贝oldfd
参数:oldfd/newfd均为文件描述符
成功:
1.关闭newfd
2.让newfd指向old对应的syruct file*结构体
失败:
1.如果oldfd是一个(无法/无效)的文件描述符,则重定向失败:newfd没有变化
2.如果oldfd和newfd的值相等,则什么事情都不干
3. 从内核角度理解重定向
文件描述符就是内核当中 fd_array数组的下标
在原程序中加入 dup(fd,1);
一号数组的下标指向了文件描述符fd
五.动态库&静态库
什么是库:静态库和动态库都是程序代码(二进制文件)的集合。一般为了方便将程序提供给第三方使用,就是将程序编写成库文件提供给第三方(用户)使用
好处:不会泄露公司的源码;调用者不必关心内部的实现,只需要关注如何使用即可。
1.动态库
特征:
windows下:没有前缀,后缀为dll
linux下:前缀为lib,后缀为.so
生成动态库:
使用gcc/g++ 编译器增加两个命令行参数 -fPIC -shared
生成动态库的代码中不需要包含main函数(程序入口函数)
配置一个简单的动态库来理解如何使用:
第一步:生成动态库
第二步:使用动态库
编译可执行程序的时候依赖动态库
-L【path】:指定动态库所在的路径
-l【动态库的名称,需要去掉前缀和后缀】:指定编译可执行程序的时候,依赖的动态库是哪个
第三步:配置环境变量
按照前俩个步骤,运行时会报错
原因:需要配置动态库环境变量
配置 LD_LIBRARY_PATH环境变量
LD_LIBRARY_PATH:一个库文件的环境变量,在~/.bash_profile或者~/.bashrc
文件中
运行成功~~
2.静态库
特征:
Windows系统下:没有前缀,后缀为./lib
Linux系统下:前缀为lib,后缀为.a
如何生成静态库文件
第一步:使用gcc/g++将源码编译成为目标程序(.o文件)
第二步:使用ar -rc 命令编译目标程序成为静态库
注意:必须使用.o
文件进行编译
运行成功~~
六.软链接&硬链接
1.软连接
目标文件的快捷方式
生成软链接文件ln -s [源文件] [软链接文件]
注意事项:
1.修改软链接文件,源文件也会被修改,修改源文件,软链接文件也会被改变
2.源文件如果被删除,软链接文件还在的,修改软链接文件。会重新建立源文件,重新建立链接关系(这种情况慎重考虑,如果之前的源文件在程序中作用很大,删除后,通过这种方式新生成的源文件与原来的已经不一样了。可能会导致程序崩溃)
建议:在删除源文件的时候,将软链接文件也一并删除掉,以防后患
软链接文件和源文件的结点号不同
2.硬链接
目标文件的替身
生成方式ln [源文件] [硬链接文件]
硬链接与源文件有着相同的节点号,且文件的硬链接数变为了2
多个文件引用同一个inode节点的时候,inode节点内部的引用计数会++
当文件删除的时候,引用计数会–,直到引用计数减为0的时候,才会释放inode节点