标准C的文件io接口:
fopen(file, "w r a b r+ w+ ") C库中fopen返回的是文件流指针: FILE*
fclose fgets fprintf
fseek跳转读写位置 printf sprintf fprintf
fread ftell
fwritex
linux下的系统调用io接口:
open
int open(const char *pathhname, int flags, mode_t mode);
pathname:要打开的文件名
flags:选项标志
O_RDONLY:只读
O_WRONLY:只写
O_RDWR:读写
O_CREAT文件不存在则创建,存在则打开
O_EXCL:与O_CREAT同用,若文件存在则报错
O_TRUNC:打开文件的同时,清空文件原有内容
O_APPEND:追加
mode:文件权限,用于创建文件的时候
返回值:正确:非负值(文件描述符) 错误:-1
close
read
返回实际读取到的数据长度
write
ssize_t write(int fd, const void *buf, size_t,count)
fd:文件描述符
buf:要写入的数据
count:要写入的数据长度
返回值:实际的写入数据长度
lseek
off_t lseek(int fd, off_t offset, int whence);
fd:文件描述符
offset:偏移值
whence:偏移起始位置
SEEK_SET:文件起始位置
SEEK_CUR:当前读写位置
SEEK_END:文件末尾位置
fileno fdopen ftruncate
库函数跟系统调用接口的关系:库函数就是系统调用接口的一层封装
文件描述符:
pcb中对文件的描述的一个结构体(file)数组下标
文件描述符是一个数字,那么一个数字是如何描述文件的呢?
一个进程要对所有打开的文件进行管理,先将文件描述起来,然后组织起来进行管理
进程中对文件进行描述的结构体:file(struct file*)
进程使用了一个结构体数组来组织这些描述,而文件描述符就是这个结构体数组的下标。
一个程序运行起来之后,默认就打开了三个文件:
标准输入,标准输出, 标准错误
stdin stdout stderr FILE* 文件流指针
0 1 2 int 文件描述符
我们所说的缓冲区(printf),用户态的一个缓冲区,是文件流指针自带的。
printf,fwrite这些可函数都是先把数据写入到缓冲区中 ,等缓冲区写满了或者一些其他条件满足然后才会真正的写入到文件中,而系统调用没有这个用户态的缓冲区(是直接将数据写入到文件中)。
文件描述符的分配规则:
最小未使用分配原则
重定向原理:
将原本描述符所对应的下标的文件描述修改成了另一个文件的描述,这样的话,描述符没有变,但是真正通过描述符操作的这个文件已经改变了。
linux下的文件系统:ext2
访问一个文件的步骤:
文件系统:
超级块, inode_map, data_map, inode, data
软硬链接:
软硬链接区别:
1.软链接可以针对目录创建,而硬链接不可以
2.软链接是一个新的文件,而硬链接是源文件的一个别名(跟源文件使用相同的inode节点)
3.软链接可以跨分区建立,但是硬链接不可以
4.源文件删除后,软链接就找不着源文件了,但是硬链接没有什么影响,仅仅是链接数-1
动态库和静态库
gcc默认链接方式:动态链接——链接是动态库
静态链接需要加上-static的gcc链接选项——链接的是静态库
静态库(.a):程序在便宜链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。
动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
程序的编译过程:预处理->编译->汇编->链接
生成一个库其实就是将所有的代码都打包起来,最终得到一个库文件。
生成动态库:gcc --share test.c -o libtest.so
编译选项:-fPIC
生成静态库:ar(创建)cr(替换) libtest.a test.c
动态库和静态库都是给其他代码使用的,意味着库中不能有main函数。
如何链接一个库生成可执行程序
gcc main.c -o main -L/ -ltest(当前路径下)
-L用于指定库的查找路径
-l用于指定链接库的名称