一、C语言IO相关函数
- FILE *fopen(const char *path, const char *mode);
- int fclose(FILE *fp);
- size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
- size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
我们看到我们可以打开一个文件进行操作,也可以关闭文件,而Linux下一切皆文件,这样我们就可以在键盘,显示器等上面打印信息,标准输入(stdin)、标准输出(stdout)、标准错误(stderr)分别对应硬件的键盘,显示器,显示器;3个标准输入输出流在C库,而硬件在底层,他们中间隔着操作系统,必定调用系统调用接口,即I/O接口。
二、系统调用接口
- int open(const char *pathname, int flags);//pathname:路径;flags:标志位(打开方式O_RDONLY,O_WRONLY,or O_RDWR)(文件创建O_CLOEXEC,O_CREAT,O_DIRECTORY,O_EXCL,O_NOCTTY,O_NOFOLLOW,O_TRUNC,and O_TTY_INIT)
- int open(const char *pathname, int flags, mode_t mode);//mode表示该文件的权限,如0644
- int creat(const char *pathname, mode_t mode);
- int close(int fd);
- ssize_t write(int fd, const void *buf, size_t count);//本次读取期望写入值,返回值为实际写入值
- ssize_t read(int fd, void *buf, size_t count);
- umask(0);是将系统掩码设为0,这样mode设置的值才能准确;
- fd是文件描述符;
- O_RDONLY(只读),O_WRONLY(只写),O_RDWR(读写)都是宏,其中O_RDWR不常用;
- O_CREAT表示该文件如果不存在则创建该文件;
- printf和fwrite都是库函数,write是系统调用函数,库函数写入文件按全缓冲刷新,写入显示器按行缓冲刷新,write不带缓冲区,如果发生重定向使得本该写入显示器而写入普通文件,则缓冲方式由行缓冲变为全缓冲;
- 以上缓冲区由C库提供;
三、fd
- 一个进程里会处理多个文件,要描述这些文件就要用到fd;
- PCB上有多个FILE结构体(files_struct),里面有一个指针数组(fd_array[]),数组下标就是某个文件的fd,数组每个元素都是FILE*类型;
- 0表示标准输入,1表示标准输出,2表示标准错误;
- 文件描述符fd从0开始;
- fd的分配规则:把最小的未被使用的fd分配给新打开的文件;
- 如果我们先关闭1号fd,在新打开一个文件,我没发现本该打印在显示器上的内容打印在了新的文件里,这就叫输出重定向;
- 同理,还有输入重定向,追加重定向等等;
四、文件系统
创建一个文件:
- 内核中先找到空闲inode节点,将位图中0置1,表示改节点被使用;
- 在该节点中记录文件信息;
- 存储数据,同样将对应位图的0置1;
- 将文件内容按块编号顺序记录到相应位置,并将块编号记录在inode节点的块列表里;
- 添加文件目录,将inode号与文件名一一映射;
硬链接&&软链接:
- 【ln】硬链接;【ln -s】软链接;
- 硬链接不新加inode号,它就是对应目标文件;只是在目录下新建立inode号与新的文件的映射关系;
- 软链接有新的inode号,它存放对于目标文件路径,指向对应文件;
- 删除对应目标文件,硬链接建立的新文件不会被删,而软链接将出错,找不到路径下的目标文件;
- 新建一个空目录,默认硬链接为2;
五、动态库&&静态库
- 动态库和静态库生成的文件都是二进制文件;
- 静态库(.a):程序编译链接时把静态库链接到可执行文件中,库里的代码被拷贝一份到程序中;
- 动态库(.so):程序在运行之前链接动态库里的代码,不拷贝到程序中;
- 动态链接的可执行文件按需加载,它有一个函数地址的表;
生成静态库:
- 【gcc -c *.c -o *.o】编译生成可执行文件;
- 【ar -rc lib-文件名.a *.o】将可执行文件打包生成静态库;
- 【gcc *.c -I.(.h路径) -L.(.a路径) -l-文件名】编译运行.c文件;
- 【ldd+可执行文件】查看链接库;
生成动态库:
- 【gcc -fPIC -c *.c】生成可执行文件;
- 【gcc -share -o lib-文件名.so *.o】以共享格式生成动态库;
- 【export LD_LIBRARY_PATH=.(.so路径)】将环境变量默认在此路径下;
- 【gcc *.c -I.(.h路径) -L.(.a路径) -l-文件名】编译运行.c文件;