| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 系统运维 -> Linux: 基础IO 重定向 静态库与动态库 -> 正文阅读 |
|
[系统运维]Linux: 基础IO 重定向 静态库与动态库 |
基础IO:库函数IO接口: FILE * fopen(char *pathname,char*mode); w 只写方式打开文件,文件不存在则自动创建,存在则清空内容? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? w+ 读写方式打开文件,文件不存在则自动创建,存在则清空内容? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?a 追加写方式打开文件,文件不存在则自动创建,存在则写入数据总是写入文件末尾? ? ? ? ? ? ? ? ? a+? 读+追加写方式打开文件,文件不存在则自动创建,存在则写入数据总是写入文件末尾? ? ? ? ? ? b二进制方式打开文件. 在系统调用IO接口中并不区分文本和二进制数据,统一按照二进制进行处理,
bsize:要写入的块大小;nmem:要写入的块个数;bsize*nmem 就是实际要写入文件的大小? ? ? ? ? ? ? fp: fopen返回的文件流指针,标识要操作哪一个文件 返回值:返回实际完整操作的块个数? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 注意:r+/w/w+方式文件打开之后,文件的默认读写位置在文件起始,如果文件中本身就有数据,就会覆盖,并且读写位置会随着数据的写入向后偏移;a/a+方式打开文件之后,读默认是从文件起始读的,但是如果写会使读写位置跳转到文件末尾,将数据追加到未尾 size_t fread(void *buf,size_t bsize,size_t nmem,FILE*fp) bsize:块大小;nmem:块个数; bsize*nmem 就是实际要读取的数据大小?, fp:fopen返回的文件流指针 注意:这个函数返回值存在多义性,返回0的时候无法直接确定是出错还是读到文件末尾了
改变文件读写位置,跳转到哪里就从哪里开始读写 fp:文件流指针; offset:偏移量;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? whence:偏移起始位置SEEK_SET-起始/SEEK_CUR-当前/SEEK_END-末尾返回值:成功返回0;失败返回-1 比如我们使用a+追加写入文件后想读取文件信息这时候我们是读不到东西的,因为读写位置已经到文件末尾了,这时我们就需要先来一个 fseek(fp,0,SEEK_SET) 使读写位置从新回到开头,再读取? ? ? ? 每次文件使用结束关闭文件释放资源,否则造成资源泄漏 系统调用IO接口: int open(char *pathname, int flag,mode_t mode); flag:文件打开标志--决定了文件的打开方式? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 返回值:成功返回一个非负整数-文件描述符-是文件的操作句柄 这个下面会讲到; 失败返回-1;? mode:文件的权限,通常采用八进制数字设定0777或0664,如果使用了O_CREAT就一定要有第三个参数,第一个数字0是不可少的.? 文件的创建权限是受到到umask掩码影响的。实际文件得到的权限mode&(~umask). mode_t umask(mode_t mask);通常在程序起始阶段调用umask(0)将当前进程的创建掩码设置为0,这样文件权限就和open的mode参数一样了,零取反得777与上mode得mode自身. 比如fopen中w+: 读写+创建+截断O_RDWR |O_CREAT |O_TRUNC
buf:一块空间地址,用于存放读取到的数据 len:要读取的数据长度 返回值:成功返回实际读取到的数据长度;失败返回-1; ssize_t write(int fd, void *data, int len) off_t lseek(int fd,off_t offset,int whence); 和fseek一样:比如我们使用a+追加写入文件后想读取文件信息这时候我们是读不到东西的,因为读写位置已经到文件末尾了,这时我们就需要先来一个 lseek(fd,0,SEEK_SET) 使读写位置从新回到开头,再读取 ??????? close(int fd);关闭文件释放资源
文件描述符就是open的返回值fd? ,? 文件流指针就是fopen的返回值fp 系统调用接口封装在库函数中,所以文件描述符也就封装在文件流指针中了. 通过下面老师画的图理解文件描述符: ??? 文件描述符本质上就是内核中,进程打开的文件IO信息指针数组的一个下标 为什么第一个打开的文件的文件描述符是3呢?因为一个进程运行之后默认会打开三个文件:stdin标准输入,stdout标准输出,stderr标准错误?. 分别为键盘,显示器,显示器,? 他们的文件描述信息分别占据了0,1,2数组下标的位置.所以0,1,2号文件描述符分别指向键盘,显示器,显示器.?再打开文件会优先放在数组下标最小的位置, 所以就成3了.? 再比如下面可以通过先close(1)断开1号文件描述符指向显示器,? 再打开一个文件,? 之后这个文件就变成1号文件描述符指向的文件,? 之后操作的东西如果原本输出到显示器的就会写入到文件里,? 而不再输出到显示器了,这也是重定向的原理:改变了文件描述符对应的文件描述信息, 就改变了操作了的文件,但文件描述符没有变. 重定向:1.如下图, 1号文件描述符是标准输出,所以write(1,str, )写入的str只会显示在屏幕(显示器)上,不会写进某个文件. 2.和上面所说,关闭1号后再打开文件会优先匹配最小的数组下标所以打开的test.txt文件的文件描述符就成了1.再write(1, ,)就会写进重定向的文件中而不会再显示在屏幕上 ? ?3.重定向的接口:dup2(int fd1,int fd2),使文件描述符fd2对应的文件描述信息改为fd1对应的文件描述信息,成功则关闭fd2原先指向的文件描述信息,这时fd1和fd2都操作fd1对应的文件 files_struct结构体中的_fileno成员就是文件描述符,? 所以也可以用下面这句stdout->_fileno=fd改变标准输出的文件描述符1 改为想给的fd.(屏幕显示器的文件流指针就是stdout). 4.文件流指针指向的结构体中不止封装有有文件描述符,还有缓冲区. 所以fwrite是有文件缓冲区的,而write就没有了.所以下面的代码运行会直接打印write,程序退出前刷新文件缓冲区才打印出缓冲区里的hello bit和fwrite 这也是系统调用接口_exit()没有缓冲区,库函数exit()有的原因.不了解缓冲区的朋友可以去看我前面写的linux进程概念与控制中文字概念中有详细介绍 标准输出重定向:>>是我们的标准输出重定向符号,一个 '>' 是清空重定向就像O_TRUNC,? 两个''>>''是追加重定向就像O_APPEND. 比如? ls >> test.txt? 就是将原本打印出来到屏幕上的当前目录下的文件信息 不再打印出来 而是重定向到指定的test.txt中.? 下面我们通过minishell理解标准输出重定向的过程! 思路是分析接收到键盘指令的cmd, 若含 '>' 符号就使该符号位置设为'\0',? '\0' 前面的字符串就是对应的指令.计算 '>' 的个数使后面在程序替换执行该执行的指令前决定重定向是追加还是清空, 设置为'\0'再往后看, >>后第一个非空格非'\0'的字符就是重定向指定文件的文件名首地址设置为filename,则位置到'\0'之间的字符串就是要写入信息的文件名. 动态库与静态库生成与使用:库的命名:一定为lib作前缀+中间自定义库名称+.os后缀(动态库)/.a后缀(静态库) 库:将很多写好的功能性代码打包成的一个文件(库中不能有main函数) 前面写的linux常用指令和常用工具gcc介绍部分中写有静态链接和动态链接的区别. 生成:嘿嘿? 使用: 1. 使用-l来指定要链接的库名称(前提是库文件需要放到指定路径下:/usr/lib64 )? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 运行可执行程序的时候使用:? ?(仅限于动态库--因为只有链接动态库,运行程序的时候才需要加载) 3.(常用)使用gcc -L选项指定库文件的所在路径(常用于链接静态库--因为静态库没有依赖,运行时不需要加载)??gcc main.c -o main -L./ -lchild? 使用main.c和自定义的库名称生成一个main可执行程序 要是没有-L./指定库文件所在路径为./(当前目录下)就需要把库文件拷贝到/usr/lib64底下 要是./下有同名的child动态静态库文件(libchild.so,libchild.a)默认链接动态库. |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/15 23:50:31- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |