目录
(1).fopen
(2).fwrite
(3).fread
(4).fseek
二.Linux环境下的系统调用IO接口认识
(1).open
(2).write
(3).read
(4).lseek
(5).close
三.文件描述符的认识
重定向的实现原理
四.动态库与静态库的打包与使用
五.文件系统
FILE* fopen(const char* filename,const char* mode);
filename:文件名
mode:打开方式
文件使用方式 | 含义 | 如果指定文件不存在 |
"r"(只读) | 为了输入数据,打开一个已经存在的文本文件 | 出错 |
"r+"(读写) | 为了读和写,打开一个文本文件 | 出错 |
"w"(只写) |
为了输出数据,打开一个文本文件 | 建立一个新的文件 |
"w+"(读写) | 为了读和写,建立一个文本文件 | 建立一个新的文件 |
"a"(追加) | 向文本文件尾添加数据 | 出错 |
"a+"(读写) | 打开一个文件,在文件尾进行读写 | 建立一个新的文件 |
“rb”(只读) | 为了输入数据,打开一个二进制文件 | 出错 |
"rb+"(读写) | 为了读和写,打开一个二进制文件 | 出错 |
"wb"(只写) | 为了输出数据,打开一个二进制文件 | 建立一个新的文件 |
"wb+"(读写) | 为了读和写,新建一个新的二进制文件 | 建立一个新的文件 |
"ab"(追加) | 向一个二进制文件尾添加数据 | 出错 |
"ab+"(读写) | 打开一个二进制文件,在文件尾进行读和写 | 建立一个新的文件 |
size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
ptr:要向文件中写入的数据
size:块大小
nmemb:块的个数
stream:fopen返回的文件描述句柄:文件流指针
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
ptr:
size:
nmemb:
stream:
返回值:实际操作的块个数,失败返回0
int fseek(FILE *stream, long offset, int whence);
stream:文件的操作句柄:文件指针流
offset:偏移量
whence:起始位置
SEEK_SET(起始位置) SEEK_CUR(当前位置) SEEK_END(末尾位置)
返回值: 成功返回0 失败返回-1
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
pathname:文件名
flags: O_RDONLY(只读) O_WRONLY(只写) O_RDWR(读写) 三选一
可选项:O_CREAT:若文件不存在则创建
O_EXCL:通常与O_CREAT同时使用,文件不存在则创建,存在则报错返回
O_APPEND:在写入的时候以追加写形式进行写入
O_TRUNC:在打开文件的同时清空文件内容
mode:文件的创建权限(在使用O_CREAT的时候这个参数必须指定文件权限)
返回值:成功返回一个非负整数(文件描述符),即系统调用IO接口的操作句柄;失败返回-1.
ssize_t write(int fd, const void *buf, size_t count);
fd:返回的文件描述符(一个进程中可能会打开很多文件,就要通过fd确定操作的是哪个文件)
buf:要写入文件的数据的首地址
count:要写入的数据长度
返回值:实际写入文件的字节长度(写入数据的时候可能会出现部分写入成功); 失败返回-1
ssize_t read(int fd, void *buf, size_t count);
fd:文件描述符
buf:缓冲区首地址(读到的数据就放到这里)
count:要读取的数据长度
返回值:成功返回实际读取到的数据的字节长度;失败返回-1
off_t lseek(int fd, off_t offset, int whence);
fd:文件描述符
offset:相对于whence的偏移量
whence: SEEK_SET(起始位置) SEEK_CUR(当前位置) SEEK_END(末尾位置)
返回值:跳转后的位置相对于文件起始位置的偏移量(有时候用于跳转到文件末尾求文件长度)
int close(int fd);
fd:文件描述符
Linux下的系统调用IO接口操作文件的打开方式中,并不区分文本操作与二进制操作,默认全部以二进制进行操作.
文件描述符:open返回的一个非负整数,是系统调用IO接口的操作句柄,通过这个数字可以让系统知道要操作哪个文件.
文件的数据实际存储在硬盘上,一个进程打开很多文件,实际上操作的时候都是操作硬盘,因此一个进程中操作很多文件,文件的数据都在磁盘的不同存储区域进行存储,因此一个进程中一旦打开一个文件,就必须描述清楚,这个文件的存储区域在哪块磁盘的哪一块区域.
文件描述符实际上就是内核中的文件描述信息数组的下标:
文件流指针:fopen返回的FILE* fp,是标准库IO接口的操作句柄
文件描述符:open返回的int fd,是系统调用IO接口的操作句柄
文件流指针与文件描述符的关系:
文件流指针是个结构体,其中包含有文件描述符作为成员变量.
库函数与系统调用接口的关系:
重定向:改变数据的流向,在不改变操作文件操作描述符的情况下,让原本要写入A文件的数据写入到B文件中.
>> : 追加重定向
> : 清空重定向
实现原理:改变内核中一个文件描述符在文件描述信息数组中对应的文件描述信息.
int dup2(int oldfd,int newfd); //让newfd也指向oldfd所指向的文件
库文件:一堆二进制代码实现的集合文件.
动态库与静态库的区别:内容上的区别和链接使用上的区别.
生成可执行程序链接动态库:只是将动态库中额函数信息表记录到可执行程序中,这种方式生成的可执行程序中没有具体的代码实现,运行时就必须依赖这个库的存在.
生成可执行程序链接静态库:将静态库中使用到的代码全部写入到可执行程序中,这种方式生成的可执行程序中拥有所有的代码实现,自己可以单独运行.
库的生成:将一大堆代码实现打包生成一个库文件(需要注意的是这些代码中不能有main函数)
打包动态库:
命名方式: 以lib作为前缀,以.so为后缀,中间是名称
打包静态库:
使用:
生成可执行程序时的链接使用:
生成可执行程序使用的是gcc编译器,在生成可执行程序的时候,使用-l选项指定要链接的库文件名称.
假如库文件名称: libtest.so/libtest.a
gcc main.c -o main -ltest
gcc编译器在生成可执行程序时,假如链接了库文件,就会默认去指定的路径下找这些库文件.
运行可执行程序时的加载使用(仅仅针对动态库):
程序运行时会自动根据程序依赖的动态库信息,去指定的动态库加载到内存加载时,就会默认的去指定的路径下找这个库文件.
概念:磁盘上管理文件存取的系统,一个磁盘上可以有多个分区,每个分区都有一个文件系统来管理这个分区的文件存储.
iNode节点:文件的元信息(包括:时间属性,权限属性,...,使用的磁盘块号)
文件存储流程:
文件数据获取流程:
软链接文件与硬链接文件:
都是针对源文件而创建出的,访问这两种文件就相当于访问源文件.
软链接文件:是一个独立的文件,有自己的iNode节点,通过保存的源文件路径访问源文件
硬链接文件:与源文件没有什么区别,都是一个文件的目录项,拥有相同的iNode节点号,通过自己的iNode节点号访问文件数据.
本质区别: