LinuxC语言文件i/o笔记(第十八天)

文件i/o

标准i/o的特点是,其使用ANSI C标准(即标准c语言),文件i/o为POSI X标准(系统文件规范),前者带有缓冲区,为流------FILE,后者不带缓冲区,为文件描述符------fcl。

在linux下,标准i/o是基于文件i/o实现的。

使用的头文件为<unistd.h>

文件描述符:

每个打开的文件都对应一个文件描述符,

其不为负,linux系统里每打开一个文件都会自动分配一个文件符。

文件i/o通过文件描述符对文件进行操作(标准i/o的输入输出流)。

文件打开:

使用函数open:

int open(const char *path,int oflag,...);

第一个参数为文件名称(地址),第二个为打开的参数(后续讲),第三个就是文件若要建立的权限(使用8进制描述)。

成功返回文件描述符,失败返回EOF。

oflag的参数:

与标准i/o相似,也有只读读写什么的:

O_ RDONLY:只读方式打开文件。

O_ WRONLY:可写方式打开文件。

O_ RDWR:读写方式打开文件。

O_CREAT:如果该文件不存在,就创建一个新的文件, 并用第三的参数为其设置权限。

O_EXCL: 如果使用O_ CREAT时文件存在,则可返回错误消息。这一参数可测试文件是否存在

O_NOCTTY:使用本参数时,如文件为终端,那么终端不可以作为调用open()系统调用的那个进程的控制终端。

O_TRUNC:如文件已经存在,那么打开文件时先删除文件中原有数据。

O_APPEND:以添加方式打开文件,所以对文件的写操作都在文件的末尾进行。

也可以选择多个参数,如我想实现如果只读一个文件,有就清空,无则新建,权限为0666:

O_ RDONLY|O_CREAT|O_TRUNC

整个函数为

fd = open("1.txt",O_ RDONLY|O_CREAT|O_TRUNC,0666);

文件的关闭:

int close(int fd);

fd为该文件的文件描述符。

成功返回0,出错返回EOF。

程序结束会自动关闭所以文件。

文件读取:

使用read函数:

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

和标准i/o按对象输入差不多,fd为文件描述符,第二个参数为缓冲区,用于存储读取的数据,第三个是要读取的数量。

成功会返回读取的实际个数,失败返回EOF。

都到末尾会返回0。

文件写入:

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

和read大致一致。

成功返回实际写入的数量,出错返回EOF。

文件的定位:

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

成功返回当前文件读取的位置,参数与标准i/o一致。

cpp 复制代码
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#define N 64
int main(int argc,char *argv[]){
        int fds,fdt,n;
        char buf[N];
        if(argc < 3){
                printf("Usage : %s <sre_file> <dst_file>\n",argv[0]);
                return -1;
        }
        if((fds = open(argv[1],O_RDONLY)) == -1){
                fprintf(stderr,"open %s : %s\n",argv[1],strerror(errno));
                return -1;
        }
        if((fdt = open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0666)) == -1){
                fprintf(stderr,"open %s : %s\n",argv[2],strerror(errno));
                return -1;
        }
        while((n = read(fds,buf,N)) > 0){
                write(fdt,buf,N);
        }
        close(fds);
        close(fdt);
        return 0;
}

库:

我们写程序的时候会用到头文件,也叫什么什么库,但是在编程过程中,如果想调用其他程序的函数,不一定要使用头文件的引用的方式,还有静态库和动态库。

静态库:

静态库是一个二进制文件,包含的代码可以被程序调用。

编译链接的时候,程序会把用得到的相关代码复制到可执行文件中,可执行程序就含有了此代码,后续运行使用都不再需要源文件,但是会占用更大的磁盘和内存。若静态库升级,还需要重新编译链接代码。

静态库程序和标准程序类似,但可以不存在int main函数,但是要有main函数。

在写完之后,原本是使用gcc -o test test.c生成可执行程序,改为 gcc -c test.c 生成二进制中间文件test.o。

再输入ar crs 静态库名称 .o文件 创建静态库,其中静态库名称由三部分组成1、lib,2、库名称,3、.a后缀,上述文件就是 ar crs libtest.a test.o。

编辑好主程序后,正在编译过程链接静态库:

gcc -o main main.c -L. -ltest

其中.c文件后面的 -L.为静态库路径,单个.表示当前目录,后续-l加库名称。

就可以实现链接啦。

动态库:

动态库是可执行文件在执行的时候才调用需要的代码模块的,多个程序可共享该库,但运行程序的时候需要源文件,否侧会报错,但升级方便,无需重新编译主程序。

动态库和静态库程序一样,但编译的时候不同:

gcc -c -fPLC test.c

才能生成动态库的二进制文件,然后建立共享库:

gcc -shared -o libcommon.so.1 test.0

其中-shared为关键字,libcommon.so.1为共享库名称,其中包括lib是固定格式,common为库名称,.so为共享库后缀,至于后面的.1是为方便管理版本什么的进行标记的。

然后还有创建关系链接:

ln -s libcommon.so.1 libcommon.so

这个就不可以有数字了

然后就是和主程序连接

gcc -o main mian.c -L. -lcommon

就可以啦。

库和头文件的对比:

特点 静态库 共享库 头文件库
文件大小 大(代码嵌入可执行文件) 小(代码在共享库中) 大(代码嵌入可执行文件)
编译方式 编译时链接 运行时链接 编译时包含
运行依赖 需要共享库文件
更新难度 难(需重新编译程序) 易(只需替换共享库文件) 易(需重新编译程序)
适用场景 小型项目、启动速度快 大型项目、更新频繁 小型库、模板库
相关推荐
mounter6256 分钟前
GCCRS 突破与 Rust 入核:Linux 工具链的重大变革
linux·开发语言·rust·linux kernel·kernel
GGMM78932 分钟前
施耐德 VX5A1HC90110(VX5A1HD9011)ATV61/ATV71 90‑110KW 电源驱动板详解
笔记·变频器·变频器维修
Wang's Blog1 小时前
PostgreSQL笔记48: 全文检索与向量检索的对比与混合检索实践
笔记·postgresql·全文检索
liuyicenysabel2 小时前
Flask 个人站 iProfile 上线笔记(k3s + Nginx + Let‘s Encrypt)
笔记·nginx·flask
caimouse2 小时前
ReactOS 窗口系统分析(25):标题栏显示与系统按钮 — nonclient.c 标题栏专题
c语言·开发语言
深蓝海拓2 小时前
基于QtPy (PySide6) 的PLC-HMI工程项目(十五)后续完善和改进:PLC端数据解析的防粘包、残包、废包、拆包
笔记·学习·plc
lxw20230271162 小时前
k8s安装部署(利用ansible)
linux·kubernetes·ansible
小黄蚁2 小时前
LVGL学习笔记(六)
笔记·学习
爱和冰阔落2 小时前
【Linux】Ctrl+C 到底做了什么?从键盘、kill 到 alarm,一次讲清信号的产生
linux·运维·c++·安卓
caimouse3 小时前
ReactOS 窗口系统分析(14):计时器/属性/加速键/热键 — timer.c + prop.c + accelerator.c + hotkey.c
c语言·开发语言·reactos