一、文件描述符
1.文件描述符下标
Linux 进程默认情况下会有3个缺省打开的文件描述符,stdin ( 0 ) , stdout ( 1 ) , stderr ( 2 ) 。
分别对应:键盘,显示器,显示器。文件描述符就是从0开始的整数。操作系统在内存中要创建相应的数据结构来描述目标文件,即file结构体。每个进程都有一个*file指针,指向一张files_struct表,该表包含了一个指针数组,每个元素都是一个指向打开文件的指针。
本质上,文件描述符就是该数组的下标。所以,只要有文件描述符,就可以找到对应的文件。
2.系统调用
① open
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
//返回值:成功返回新分配的文件描述符,出错返回-1并设置errno
//参数:pathname,要打开或创建的文件名,和fopen一样,pathname既可以是相对路径也可以是绝对路径;flags,有一系列常数值可供选择,可以同时选择多个常数用按位或运算符连接起来,所以这些常数的宏定义都以O_开头,表示or;mode,权限。
必选且只能选一个:
•O_RDONLY 只读打开
•O_WRONLY 只写打开
•O_RDWR 可读可写打开
可以同时选一个或多个:
•O_APPEND 表示追加。如果文件已有内容,这次打开文件所写的数据附加到文件的末尾而不覆盖原来的内容。
•O_CREAT 若此文件不存在则创建它。使用此选项时需要提供第三个参数mode,表示该文件的访问权限。
•O_EXCL 如果同时指定了O_CREAT,并且文件已存在,则出错返回。
•O_TRUNC 如果文件已存在,并且以只写或可读可写方式打开,则将其长度截断(Truncate)为0字节。
•O_NONBLOCK 对于设备文件,以O_NONBLOCK方式打开可以做非阻塞I/O(Nonblock I/O)。
② read
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t nbytes);
//参数:fd,文件描述符;buf,缓冲期地址;nbytes,本次读取多少个字节
//返回值:成功,返回实际读到的字节数,若已到文件尾,返回0;失败返回-1
③ write
#include <unistd.h>
ssize_t write(int fd, void *buf, size_t nbytes);
//参数:fd,目标文件描述符;buf,缓冲区指针;len,本次读取,期望写入多少字节的数据
//返回值:成功,返回实际写了多少个字节的数据;失败返回-1 或 返回值小于nbytes时,内核很可能会再次写余下的数据,形成死循环,文件系统写满,系统挂了!
在写实际的文件系统的写操作时一定要注意其返回值,否则可能系统崩溃了。
④ close
#include <unistd.h>
int close(int fd);
//返回值:成功返回0,出错返回-1并设置errno
//参数:fd,要关闭的文件描述符
3.重定向
本来应该输出到显示器上的内容,输出到文件内,称为重定向。常见的重定向有:> , >> , <
① 文件描述符分配规则
0往后第一个空闲下标,分配给文件
关闭标准输出,文件的文件描述符变为fd(1),fd(1)中地址已经变为new_file的地址,输出的消息都将写入new_file文件中
4.缓冲方式
① 行缓冲 \n
往标准输出中写
② 全缓冲
往文件中写
③ 没缓冲
printf , fwrite等库函数会自带缓冲区当发生重定向到普通文件时,数据的缓冲方式由行缓冲变为全缓冲;缓冲区是由C标准库二次加上的
write等系统调用*有自带缓冲区
二、文件系统
1.文件系统结构
① 超级块
- 文件系统元信息
②iNode区
- 保存文件元信息
③block区
- 管理n个block
2.软硬链接
①硬链接
不同文件名访问同一个iNode
通过inode引用另外一个文件
②软链接
通过名字引用另外一个文件
- 快捷方式:特殊的文件类型,保存了另一个文件的全路径
三、静态库与动态库
1.背景
静态库
发布方便,只需要发布一个可执行程序
动态库
发布时需要带上所有依赖的动态库,更新程序的某个模块时较为方便
2.gcc选项
静态库
本质上是“.o”文件的打包,ar -rc
//静态库 makefile
test:test.c libadd.a
gcc test.c ./libadd.a -o test
libadd.a:add.o
ar -rc libadd.a add.o
add.o:add.c
gcc -c add.c -o add.o
.PHONY:clean
clean:
rm test libadd.a add.o
动态库
shared :表示生成共享库格式
fPIC :产生位置无关码(position independent code)
库名规则 :libxxx.so
//动态库 makefile
test:test.c libadd.so
gcc test.c ./libadd.so -o test
libadd.so:add.c
gcc add.c -o libadd.so -fPIC -shared
.PHONY:clean
clean:
rm test
$ ldd test 查看
和库一起编译选项-L 指定查找路径
-l 库名 库文件的文件路径
3.相关环境变量
运行动态库
拷贝 .so文件到系统共享库路径下
更改LD_LIBRARY_PATH
echo $LD_LIBRARY_PATH
echo 环境变量