Linux之系统编程之基础IO

一、标准库IO

1.回顾函数

①fopen(char* filename, char* mode);

  • r 只读
  • r+ 可读可写
  • w 只写
  • w+ 可读可写
  • a 追加只写
  • a+ 追加可读可写

②fread(char* buf, size_t bsize, size_t nnum, FILE* fp);
③fwrite(char* data, size_t bsize, size_t nnum, FILE* fp);
④fseek(FILE* fp, size_t offset, int whence);

  • SEEK_SET
  • SEEK_CUR
  • SEEK_END

⑤fclose(FILE* fp);
⑥fgets(char* buf, size_t size, FILE* fp);
⑦fprintf(FILE* stream, const char* format)
⑧stdin 标准输入,stdout标准输出,stderr标准错误。

2.注意事项

  • 打开模式a,写入的时候总是写入文件末尾,并且不管读写位置如何跳转。
  • fread/fwriter返回值都是块个数,而不是数组字节长度,因此写法块大小给1,更利于使用。
  • 从文件中读取的数据进行字符串处理时需要注意,文件内容中可能有空数据,导致文件内容字符串处理不完全。
  • 非以追加方式打开时,文件的默认读写位置在起始位置,煮一会覆盖式写入数据。
  • w方式打开文件时,会清空原有内容。

二、系统调用接口

①open(char* filename, int flag, mode_t mode);

  • flag :
    必选选项三者必须选一个:
    O_RDONLY 只读
    O_WRONLY 只写
    O_RDWR 可读可写
    可选选项:
    O_CREAT若文件不存在则创建,若存在则打开
    O_APPEND写入数据,使用追加写的方式
    O_TRUNC打开文件时清空原有数据
    O_EXCL一般与O_CREAT一起使用,若文件不存在则创建,若文件存在则报错。如flag:O_RDWR | O_CREAT | O_TRUNC
  • mode:当使用O_CREAT的时候可能新建文件,因此需要指定文件权限。mode&(~umask) = 实际最终得到的文件权限。
  • open返回值:错误返回-1,成功返回一个非负整数(文件描述符:打开文件的操作句柄,可通过句柄操作文件。)

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

  • fd:open返回的文件描述符
  • buf:要写入的数据的缓冲区首地址
  • count:要写入的数据长度
  • 返回值:成功返回写入数据的字节数,失败返回-1

③read:size_t read(int fd, void* buf, size_t count)

  • fd:open返回的文件描述符
  • buf:数据放置的缓冲区首地址
  • count:想要读取的数据长度
  • 返回值:成功时返回实际读取的字节数,失败时返回-1,返回0则表示读取到了文件末尾。

④lseek:off_t lseek(int fd, off_t offset, int whence);跳转读写位置

  • fd:open返回的文件描述符
  • whence有三种:SEEK_SET(文件开始的位置)、SEEK_END(文件结束的位置)、SEEK_CUR(文件当前的位置)。
  • 在读写文件时,写入文件后需要lseek将文件指针指向文件开始位置,否则会从文件最后的位置开始读。
  • 返回值:成功时返回0,失败时返回-1、

⑤注意事项:当打开文件时使用了O_CREAT,就一定不能忘记添加open第三个参数-----权限。

三、文件描述符

在这里插入图片描述

  • 文件描述符:内核中文件描述信息结构struct file数组的下标,通过文件描述符在pcb中的files_struct结构体的fd_array[]数组中找到相应文件描述信息,进而对文件进行操作。
  • 文件描述符int fd;系统调用接口的操作句柄
  • 文件流指针FILE* fp;库函数接口的操作句柄
  • 文件流指针这个结构体中就包含了文件描述符,当我们使用标准库接口进行IO时,则最终是通过文件流指针找到文件描述符进而对文件进行操作。
  • 标准输入----0----stdin
  • 标准输出----1----stdout
  • 标准错误----2----stderr
  • 之前所说的缓冲区实际上是文件流指针所维护的一块缓冲区。叫用户态的缓冲区。
  • 用户态的缓冲区使用是用户空间的地址。
  • 运行库函数时,是用户态的缓冲区。
  • 运行系统调用接口时,是内核态的缓冲区。
  • 程序是运行在内核态还是用户态?----当前运行的接口是否程序员自己写的。

四、重定向

  • 本质:是对文件描述符的重定向。
  • 我们操作一个文件时,都是通过描述符操作的,当这个描述符对应在内核中文件描述符信息表中的描述信息,若改变成另一个文件描述符信息,会造成一个情况:操作的文件描述符没有变,但具体的文件却改变了。
  • 使用dup2函数进行系统调用。原型:int dup2(int oldfd, int newfd);(#include <unistd.h>)如下所示
    在这里插入图片描述

五、文件系统的基本认识

1.磁盘与文件

  • 磁盘分区:交换分区 + 文件系统分区。其中文件系统分区可以有多个。
    在这里插入图片描述
  • 超级块:存储文件系统信息,文件系统类型,各个区域首地址,磁盘块大小,有多少块,有多少使用了,有多少未使用。
  • inode_bitmap:通过二进制存储inode节点的使用状况。
  • data_bitmap:通过二进制位图存储数据区域数据块的使用情况。
  • inode area:inode table,这个区域存存储都是inode节点。
  • 每个文件都有唯一的inode节点。

(1)从磁盘中存储文件的流程:

  • 在超级块中找到inode table首地址,以及inode_bitmap首地址,快速找到一个空闲的inode节点。
  • 在超级块中找到data数据块地址,以及data_bitmap首地址,快速找到对应个数的空闲数据块。
  • 在inode节点中添加文件元信息,以及数据块号。
  • 在文件所在目录中添加文件的目录项----目录文件的数据块中存储的是目录项(文件名 - inode节点号)

(2)从磁盘上找到一个文件的流程:

  • 通过文件名,在所在目录的目录项中找到文件对应的inode节点。
  • 在inode_table中快速找到inode节点,获取元信息以及数据块号。
  • 通过数据块号,可以在磁盘的数据块上找到文件数据。

2.软链接/硬链接

  • 可以通过软链接/硬链接文件操作源文件。

(1)如何创建软链接文件以及硬链接文件

  • 创建软链接文件:ln -s tmp.txt tmp.soft
  • 创建硬链接文件:In tmp.txt tmp.hard

(2)本质区别

  • 软链接文件是一个独立的文件,类似于文件的快捷方式,有自己的inode节点。而硬链接文件是一个文件的目录项,类似于一个文件的别名。与源文件指向相同的一个inode节点。
  • 软链接文件通过存储的源文件路径找到源文件inode,进而访问文件数据。但是硬链接通过自己的inode节点号直接访问文件数据。
  • 删除源文件时,软链接失效,硬链接仅仅是链接数减1,依然可以访问。(删除一个文件时,是删除一个目录项,当该文件链接数为0时才是真正删除。)
  • 软链接可以跨分区建立,但是硬链接不可以。
  • 软链接可以对目录创建,但是硬链接不可以。

六、动态库和静态库

1.动态库和静态库的概念

  • 静态库(.a):程序在编译链接的时候把库的代码连接到可执行文件中。程序运行的时候不再需要静态库。
  • 动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
  • 一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标的整个机器码。
  • 在可执行文件开始运行之前,外部函数的机器码由操作系统从磁盘上的该动态库复制到内存中,这个过程称为动态链接。
  • 动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间。

2.动态库和静态库的生成和使用

(1)动态库的生成(库名称前面加lib后面加.so)

  • gcc -fPIC -c text.c -o text.o
  • gcc -shared text.o -o libtext.so
  • 其中shared表示生成共享库格式。fPIC是产生位置无关码。
  • 库名规则:libxxx.so

(2)动态库的使用

  • l:链接动态库,只要库名即可(去掉lib以及版本号)
  • L:链接库所在的路径
  • 如:gcc main.o -o mian -L. -ltext

(3)静态库的生成:gcc/ar

  • gcc -c text.c -o text.o
  • ar -cr libtext.a text.o

(3)库的使用

  • 链接的时候使用库:① 将库文件放到指定路径下(Linux有一个放库文件的指定目录)。 ② 设置LIBRARY_PATH环境变量。 ③ 通过gcc -L选项设置链接库的默认搜索路径。gcc -o main main.o -L ./ -ltext
  • 运行时使用库:① 将库文件放到指定路径下(Linux有一个放库文件的指定目录)。 ② 设置LD-LIBRARY_PATH环境变量。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值