Linux:基础IO

库函数IO接口

fopen,fwrite,fread,fseek,fclose
FILEfopen(charpathname,char*mode);
pathname:文件路径名 mode:文件打开方式
在这里插入图片描述
系统调用IO接口中并不区分文本和二进制数据,统一按照二进制进行处理,但是库函数不一样,区分文本和二进制,默认文本操作,但是有的文本一个字符占多个字节,例如:一个文件中有十个字节数据,但是读取完毕后大小是9,这个9表示的不是9个字节,而是九个字符
返回值:打开文件成功则返回一个FILE文件流指针作为文件的操作句柄,失败返回NULL
**size_t fwrite(const void
data,size_t bsize,size_t nmem,FILIEfp)**
data:要写入文件数据的所在空间首地址;
bsize:块大小 nmem:块个数;bsize
nmem :实际写入文件大小
fp:fopen返回的文件流指针,标识要操作哪一个文件
返回值:返回实际完整操作的块个数
注意:r+/w/w+方式打开后,文件的默认位置是在文件的起始位置,如果文件本身就有数据,就会覆盖,并且读写位置会随数据的写入向后偏移;a/a+方式打开文件后,读默认是从文件起始位置读的,但是如果写会跳转到文件末尾,将数据追加
size_fread(voidbuf,size_t bsize,size_t nmem,FLIEfp)
buf:一块空间的首地址用于存放从文件中读取的数据
bsize:块大小;nmem:块个数;bsizenmem:实际读取的数据大小;
fp:文件流指针
返回值:成功返回实际操作的完整块个数,读取到文件末尾了返回0,出错了返回0;
注意:这个函数的返回值存在多义性,返回0的时候无法确定出错了还是读取到文件末尾了;例如一个文件100字节,我现在读取数据块大小200,块个数为1,因为没有读到完整一块,并且读到了文件末尾因此返回了一个0,这个时候这个0就无法确认是出错了还是正常的;因此建议fread读取数据的时候,块大小设置为1,想要读取的长度设置为块个数,这样返回值就能告诉我们读取了多少数据
**int fseek(FILE
fp,int offset,int whence);**
改变文件读写位置,跳转到哪里就从哪里开始读写
fp:文件流指针;offset:偏移量;whence:偏移起始位置
SEEK_SET-起始/SEEK_CUR-当前/SEEK_END-末尾
返回值:成功返回0;失败返回-1
int fclose(FILE*fp):关闭文件释放资源

Linux系统调用接口

open,read,write,lseek,close
int open(char pathname,int flag,mode_t mode)
pathname:要打开的文件路径名
flag:文件打开标志–决定了文件打开方式。
必选标志:O_RDONLY-只读|O_WRONLY–只写|O_RDWR-读写 只能选择其中一个 不能同时使用
可选标志:O_APPEND-追加写|O_CREAT-文件不存在则创建|O_TRUNC-文件不存在则截断为0|O_EXCL-文件存在则报错
w+:读写+创建+截断 O_RDWR|O_CREAT|O_TRUNC
a+:读+追加写+创建O_RDWR|O_APPEND|O_CREAT
mode:文件的权限,通常采用八进制狮子设定 0777 ,如果使用了O_CREAT则一定要有第三个参数
文件的创建权限是受到umask掩码影响的。实际文件得到的权限 mode&(~umask)
mode_t umask(mode_t mask):通常在程序起始阶段调用umask(0)将当前进程的掩码设置为0
返回值:成功返回一个非负整数-文件描述符-是文件的操作句柄;失败返回-1;
ssize_t read(int fd,void buf,int len);
fd:open返回的文件描述符-操作句柄-表示操作那个文件
buf:一块空间地址,用于存放已读取到的数据
len:表示要读取的长度
返回值:返回读取到的内存长度,失败返回-1
ssize_t:这个数据类型用来表示可以被执行读写操作的数据块的大小.它和size_t类似,但必需是signed.意即:它表示的是sign size_t类型的。
ssize_t write(int fd, void*data,int len);
fd:文件描述符-操作句柄;
data:要写入数据的空间首地址;
len:要写入文件的数据长度;
返回值:成功返回数据长度;失败返回-1;
off_t lseek(int fd,off_t offset,int whence);
fd:文件描述符;
offset:偏移量;
whence:偏移起始位置SEEK_SET|SEEK_CUR|SEEK_END
返回值:成功返回跳转后的位置相对于文件的起始长度(额外用法:跳转到文件末尾则返回文件长度);失败返回-1
int close(int fd)
关闭释放文件资源

文件描述符-文件流指针

文件描述符:open返回的一个非负整数-int
文件流指针封装了文件描述符
文件描述符本质上就是内核中,进程打开文件IO信息指针数组的一个下标,当我们通过文件描述符操作文件的时候,在pcb中找到files_struct结构体指针,进而找到结构,找到结构体中的数组,以描述符作为下标获取到文件描述信息的地址,通过描述信息操作文件
文件流指针:struct FILE*
文件操作符与文件流指针:文件流指针struct FILE中封装了文件描述符,并且还包含了一个用户态缓冲区
文件流指针是库函数的操作句柄,文件操作符是系统调用接口的操作句柄
库函数和系统调用接口是一层上下级调用的关系:库函数封装的就是系统调用接口
fwrite(用的是文件流指针)->write(用的是文件操作符)

重定向原理

重定向:改变了数据的流向,让原本写入A文件的数据,不在写入A文件而是写入B文件中。
一个进程运行起来之后,默认会打开三个文件:标准输入,标准输出,标准错误
而这三个文件占据的描述符就是0-标准输入,1-标准输出,2-标准错误
标准输出重定向的原理:
在这里插入图片描述
1描述符默认是显示器文件,但是一旦重定向,就会让1描述符不在指向显示器,而是指向指定的文件描述信息,这时候,原本写入到1中的数据,就没有在写入到显示器了,而是写入到指定文件中,所有代码没有改版,只是改变了文件描述信息数组中下标对应的描述信息指针

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

静态库(.a):程序在编译链接的时候把库的代码连接到可执行文件中。程序运行的时候将不再需要静态库。
动态库(.so):程序在运行的时候采取链接看动态库代码,多个程序共享使用库的代码。
1.一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码
2.在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接(dynamic linking)
3.动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间。
生成静态库
在这里插入图片描述
生成动态库
shared:表示生成共享库格式
fPIC:产生位置无关码
库名规则:libxxxx.so
示例: [root@localhost linux]# gcc -fPIC -c sub.c add.c
[root@localhost linux]# gcc -shared -o libmymath.so*.o
[root@localhost linux]# ls add.c add.h add.o libmymath.so main.c sub.c sub.h sub.o
使用动态库
在这里插入图片描述
运行动态库
在这里插入图片描述

Guess you like

Origin blog.csdn.net/qq_56813393/article/details/121467965