Linux 基础IO相关知识总结

目录

(1).fopen

(2).fwrite

(3).fread

(4).fseek

二.Linux环境下的系统调用IO接口认识

(1).open

(2).write

(3).read

(4).lseek

(5).close

三.文件描述符的认识

重定向的实现原理

四.动态库与静态库的打包与使用

五.文件系统


(1).fopen

FILE*  fopen(const char* filename,const char* mode);
filename:文件名
mode:打开方式
文件打开方式
文件使用方式 含义 如果指定文件不存在
"r"(只读) 为了输入数据,打开一个已经存在的文本文件 出错
"r+"(读写) 为了读和写,打开一个文本文件 出错

"w"(只写)

为了输出数据,打开一个文本文件 建立一个新的文件
"w+"(读写) 为了读和写,建立一个文本文件 建立一个新的文件
"a"(追加) 向文本文件尾添加数据 出错
"a+"(读写) 打开一个文件,在文件尾进行读写

建立一个新的文件

“rb”(只读) 为了输入数据,打开一个二进制文件 出错
"rb+"(读写) 为了读和写,打开一个二进制文件 出错
"wb"(只写) 为了输出数据,打开一个二进制文件 建立一个新的文件
"wb+"(读写) 为了读和写,新建一个新的二进制文件

建立一个新的文件

"ab"(追加) 向一个二进制文件尾添加数据 出错
"ab+"(读写) 打开一个二进制文件,在文件尾进行读和写 建立一个新的文件

(2).fwrite

size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
ptr:要向文件中写入的数据
size:块大小
nmemb:块的个数
stream:fopen返回的文件描述句柄:文件流指针

(3).fread

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
ptr:
size:
nmemb:
stream:

返回值:实际操作的块个数,失败返回0

(4).fseek

int fseek(FILE *stream, long offset, int whence);
stream:文件的操作句柄:文件指针流
offset:偏移量
whence:起始位置
       SEEK_SET(起始位置)   SEEK_CUR(当前位置)   SEEK_END(末尾位置)
返回值: 成功返回0   失败返回-1

二.Linux环境下的系统调用IO接口认识

(1).open

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.

(2).write

ssize_t write(int fd, const void *buf, size_t count);
fd:返回的文件描述符(一个进程中可能会打开很多文件,就要通过fd确定操作的是哪个文件)
buf:要写入文件的数据的首地址
count:要写入的数据长度
返回值:实际写入文件的字节长度(写入数据的时候可能会出现部分写入成功); 失败返回-1

(3).read

ssize_t read(int fd, void *buf, size_t count);
fd:文件描述符
buf:缓冲区首地址(读到的数据就放到这里)
count:要读取的数据长度
返回值:成功返回实际读取到的数据的字节长度;失败返回-1

(4).lseek

off_t lseek(int fd, off_t offset, int whence);
fd:文件描述符
offset:相对于whence的偏移量
whence: SEEK_SET(起始位置)  SEEK_CUR(当前位置)   SEEK_END(末尾位置)
返回值:跳转后的位置相对于文件起始位置的偏移量(有时候用于跳转到文件末尾求文件长度)

(5).close

int close(int fd);
fd:文件描述符

Linux下的系统调用IO接口操作文件的打开方式中,并不区分文本操作与二进制操作,默认全部以二进制进行操作.

三.文件描述符的认识

文件描述符:open返回的一个非负整数,是系统调用IO接口的操作句柄,通过这个数字可以让系统知道要操作哪个文件.

文件的数据实际存储在硬盘上,一个进程打开很多文件,实际上操作的时候都是操作硬盘,因此一个进程中操作很多文件,文件的数据都在磁盘的不同存储区域进行存储,因此一个进程中一旦打开一个文件,就必须描述清楚,这个文件的存储区域在哪块磁盘的哪一块区域.

Linux 基础IO相关知识总结_第1张图片

文件描述符实际上就是内核中的文件描述信息数组的下标:

  1. 进程中打开一个文件,就会创建一个struct file结构体描述这个文件信息
  2. 将这个结构体存储空间的地址,放到进程的文件描述信息数组中
  3. 将数组放置描述信息的这个节点的下标作为文件描述符返回给用户

文件流指针:fopen返回的FILE* fp,是标准库IO接口的操作句柄

文件描述符:open返回的int fd,是系统调用IO接口的操作句柄

文件流指针与文件描述符的关系:

文件流指针是个结构体,其中包含有文件描述符作为成员变量.

库函数与系统调用接口的关系:

  • 系统调用接口:是操作系统向上提供的访问内核的接口.
  • 库函数:是对系统调用接口封装后的接口函数.

重定向的实现原理

重定向:改变数据的流向,在不改变操作文件操作描述符的情况下,让原本要写入A文件的数据写入到B文件中.

>> : 追加重定向

>   : 清空重定向

实现原理:改变内核中一个文件描述符在文件描述信息数组中对应的文件描述信息.

int dup2(int oldfd,int newfd); //让newfd也指向oldfd所指向的文件

四.动态库与静态库的打包与使用

库文件:一堆二进制代码实现的集合文件.

动态库与静态库的区别:内容上的区别和链接使用上的区别.

生成可执行程序链接动态库:只是将动态库中额函数信息表记录到可执行程序中,这种方式生成的可执行程序中没有具体的代码实现,运行时就必须依赖这个库的存在.

生成可执行程序链接静态库:将静态库中使用到的代码全部写入到可执行程序中,这种方式生成的可执行程序中拥有所有的代码实现,自己可以单独运行.

库的生成:将一大堆代码实现打包生成一个库文件(需要注意的是这些代码中不能有main函数)

  1. 将我们自己写的各个.c源码,编译称为二进制代码
  2. 将各个c源码的二进制代码进行打包,打包成库文件

打包动态库:

  • gcc -fPIC -c child.c -o child.o   先将源码编译为二进制文件
  • gcc --shared child.o -o libchild.so    --shared 告诉编译器生成的是库文件而不是可执行文件

命名方式: 以lib作为前缀,以.so为后缀,中间是名称

打包静态库:

  • gcc -c child.c -o child_static.o  生成二进制文件
  • ar -cr libchild.a child.o    使用ar工具打包静态库

使用:

生成可执行程序时的链接使用:

生成可执行程序使用的是gcc编译器,在生成可执行程序的时候,使用-l选项指定要链接的库文件名称.

假如库文件名称: libtest.so/libtest.a

gcc main.c -o main -ltest

gcc编译器在生成可执行程序时,假如链接了库文件,就会默认去指定的路径下找这些库文件.

  1. 将库文件放到默认指定的路径下 /lib64
  2. 环境变量LIBRARY_PATH保存默认查找路径,将库文件所在路径添加到环境变量中 export LIBRARY_PATH=$LIBRARY_PATH:.
  3. 使用gcc编译选项-L指定库文件所在路径: gcc main.c -o main -lchild -L./

运行可执行程序时的加载使用(仅仅针对动态库):

程序运行时会自动根据程序依赖的动态库信息,去指定的动态库加载到内存加载时,就会默认的去指定的路径下找这个库文件.

  1. 将库文件放到指定的路径 /lib64
  2. 环境变量LD_LIBRARY_PATH保存加载路径

五.文件系统

概念:磁盘上管理文件存取的系统,一个磁盘上可以有多个分区,每个分区都有一个文件系统来管理这个分区的文件存储.

Linux 基础IO相关知识总结_第2张图片

iNode节点:文件的元信息(包括:时间属性,权限属性,...,使用的磁盘块号) 

文件存储流程:

  1. 在超级块中获取文件系统信息(各个区域的起始位置),找到两个位图区域
  2. 根据位图信息,找到空闲的iNode节点,以及空闲的数据块
  3. 存储数据到数据块中,存储文件的元信息到iNode节点中
  4. 将文件名与iNode节点号作为对应信息(目录项)保存在所在目录的文件中

文件数据获取流程:

  1. 通过文件的路径名,打开文件所在的目录文件,获取到文件的目录项(得到文件的iNode节点号)
  2. 通过iNode节点号,找到文件的iNode节点,获取到文件数据存储的磁盘块号
  3. 在指定的磁盘块中取出数据

软链接文件与硬链接文件:

都是针对源文件而创建出的,访问这两种文件就相当于访问源文件.

软链接文件:是一个独立的文件,有自己的iNode节点,通过保存的源文件路径访问源文件

硬链接文件:与源文件没有什么区别,都是一个文件的目录项,拥有相同的iNode节点号,通过自己的iNode节点号访问文件数据.

本质区别:

  1. 删除源文件,则软链接文件会失效,但是硬链接文件不受影响
  2. 软链接文件可以跨分区建立,但是硬链接文件不可以
  3. 软链接文件可以对目录创建,但是硬链接文件不可以

 

 

 

你可能感兴趣的:(linux)