1.标准库IO接口

 文件流指针(FILE *fp)

stdin(标准输入)   stdout(标准输出)   stderr(标准错误)

//打开文件
FILE *fopen(const char* filename,const char* mode)

   mode有:r、r+、w、w+、a、a+

  • r:只读,打开在文件的起始位置
  • r+:可读可写,打开在文件的起始位置
  • w:只写,文件不存在则创建文件,文件存在则清空文件,打开在文件的起始位置
  • w+:可读可写,在写入文件的时候会清空原有的内容,打开在文件的起始位置
  • a:以追加的方式写入,追加到文件末尾,文件不存在则创建文件,打开文件直接显示在文件末尾
  • a+:以读和追加写的方式,打开文件显示在文件的起始位置,当开始写数据时,跳转到文件末尾

 

//读取文件
size_t fread(void *ptr,size_t size,size_t nmemb,FILE *stream);

//写入文件
size_t fwrite(const void *ptr,size_t size,size_t nemeb,FILE *stream);

fread、fwrite返回值都是块个数,而非实际读取/写入的数据字节长度,因此使用时通常块大小为1,而块的个数是数据长度,这样才能返回读取/写入的数据长度

 

//跳转到文件的读写位置
int fseek(FILE *stream,long offset,int whence);

 whence有三个值:SEEK_SET(文件开头)、SEEK_CUR(当前位置)、SEEK_END(文件结尾)

offset表示以whence为基准,偏移多少字节,整数表示正向偏移,负数表示负向偏移

2.系统调用接口

常见接口:open、read、write、lseek、close


 

1.open

int open(const char *pathname,int flags,mode_t mode);

    参数信息:

  • pathname:带路径文件名
  • flags:选项参数
  • mode:若有可能创建新文件则需要指定文件权限(例如输入权限为可读可写可执行,则需要输入0777)
  • 返回值:文件的操作句柄,错误返回-1
mode_t umask(mode_t mask);
//设置文件的创建权限掩码,决定了文件的默认权限
//用法:给定权限 & ~掩码
//如果有O_CREAT(创建)一定要使用mode设置权限

flags(选项参数)

必选项:O_RDONLY、O_WRONLY、O_RDWR(只读、只写、可读可写三选一) 

可选项:

  1. O_CREAT:文件不存在则创建新文件,存在则打开
  2. O_EXCL:文件不存在则创建新文件,存在则报错
  3. O_TRUNC:打开文件的同时截断文件
  4. O_APPEND:写入数据的时候总是追加在文件末尾

w+:O_RDWR|O_CREAT|O_TRUNC

a+:O_RDWR|O_EXCL|O_APPEND

 

2.write

ssize_t write(int fd,const void *buf,size_t count);

    参数信息:

  • fd:文件描述符
  • buf:要写入文件的数据缓冲区首地址
  • count:要写入的数据长度
  • 返回值:实际写入文件中的数据字节长度(不一定等于count),失败返回-1

 

3.read

ssize_t read(int fd,void *buf,size_t count);

   参数信息:

  • fd:文件描述符
  • buf:缓冲区首地址,放入读取到的数据
  • count:要读取的数据长度,大小不能大于缓冲区大小
  • 返回值:返回读取到的数据字节长度(不一定等于count),返回0表示读到文件末尾,失败返回-1
mode_t umask(mode_t mask);
//设置文件的创建权限掩码,决定了文件的默认权限

 

4.lseek

off_t lseek(int fd,off_t offset,int whence);

 参数信息:

  • fd:文件描述符
  • offset:偏移量
  • whence:跳转到的位置

 

5.close

int close(int fd);

关闭文件描述符,不关闭文件描述符会导致资源泄漏

3.文件描述符(fd)

文件描述符时内核中struct file* fd arry[]数组的下标,进程可以通过这个下标找到文件的描述信息,进而操作文件

文件描述符的分配规则:最小未使用

一个程序运行起来,默认会打开三个文件,文件描述符默认从3开始

Linux下的基础IO_静态库

4.文件流指针和文件描述符的关系

文件流指针库函数IO接口的操作句柄

文件描述符系统调用IO接口的操作句柄


 文件流指针是一个结构体封装了文件描述符

5.重定向的实现原理

针对文件描述符所对应的文件描述信息的重定向,此时操作文件描述符 / 文件流指针并没有发生改变,但实际操作的文件已经发生改变


 常见的重定向:>、>>、<

ls 1 >> a.txt : 将标准输出重定向到a.txt

ls 2 >> &1 : 将标准错误重定向到标准输出

>> 是追加重定向

> 是清空重定向

6.文件系统==磁盘文件管理

文件系统分区

Linux下的基础IO_结点_02

  • 超级块:描述文件系统,以及inode使用情况和磁盘块使用情况
  • inode_map:inode结点位图,快速查找未使用的结点位置
  • data_map:磁盘块位图,快速查找未使用的磁盘块位置
  • inode结点:存储文件的元信息,磁盘块位置
  • data:磁盘块,存储数据,实现离散式存储

       目录也是文件,inode结点和文件名称作为目录项存储在目录文件中


 

文件存储流程:

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

文件数据获取流程:

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

7.软链接文件与硬链接文件的区别

不论是软链接文件还是硬链接文件,目的都是为了通过这些文件访问到源文件


 

1 ln filename   //创建硬链接(创建好的文件后缀名:.hard)
2 ln -s filename   //创建软链接(创建好的文件后缀名:.soft)
3 ls -i   //查看文件的inode结点号
  • 硬链接文件跟源文件拥有相同的inode结点,类似于源文件的一个别名,通过自己的inode结点访问源文件。
  • 软链接文件是一个独立的文件,有自己的inode结点(与源文件不同),通过保存源文件的路径进而访问源文件。
  • 删除源文件,软链接文件失效;硬链接文件不失效,只是链接数-1(如果链接数为0,则销毁inode结点,释放空间)
  • 软链接文件可以针对目录创建;硬链接不可以
  • 软链接文件可以跨分区建立;硬链接不可以

8.静态库与动态库的生成与使用

静态库的生成:

1 gcc -c child.c -o child.o   //生成.o文件
2 ar -cr libmychild.a child.o
3 //静态库名称:lib[filebname].a

动态库的生成:

1 gcc -fPIC -c child.c -o child.o   //生成.o文件
2 gcc --share -o libmychild.so child.o
3 //-fPIC的作用:产生一个未知无关代码
4 //动态库名称:lib[filebname].so

使用:

  • 在生成可执行程序时链接时使用:
  1. 将库文件放置到指定路径下(库文件的搜索路径默认/lib64)
  2. 设置环境变量LIBRARY_PATH,将库文件所在目录路径添加到这个环境变量的值中
  3. 使用gcc -L 选项,指定gcc库文件的搜索路径
  • 在运行可执行程序的时候加载使用:(仅针对动态库)
  1. 将库文件放置到指定路径下(库文件的搜索路径默认/lib64)
  2. 设置环境变量LD_LIBRARY_PATH

注意:

      我们在链接静态库时,并不是使用-static去指定gcc进行静态链接

      因为-static的功能是在生成可执行程序的时候,所有的依赖库都是静态库,不仅仅是指定的那个库

       通常在链接一个静态库的时候,都是将这个静态库放到指定路径下,直接链接这个静态库,而其他的依赖库依然会使用动态库链接