Linux——基础IO&链接&动静态库
目录
、
只有认知的突破💫才能带来真正的成长💫编程技术的学习💫没有捷径💫一起加油💫

🍁感谢各位的观看🍁欢迎大家留言🍁咱们一起加油🍁努力成为更好的自己🍁
基础IO
在Linux中,“一切皆文件”。所以IO操作就是进程和文件之间进行数据的交互。
FILE*
在C语言中,文件指针FILE*对应的是FILE结构体,其结构如下所示。
typedef struct _IO_FILE {
int _flags; // 文件状态标志(如只读、可写、错误、EOF等)
char* _IO_read_ptr; // 缓冲区当前读取位置
char* _IO_read_end; // 缓冲区读取结束位置
char* _IO_read_base; // 缓冲区起始地址(读缓冲区)
char* _IO_write_base;// 缓冲区起始地址(写缓冲区)
char* _IO_write_ptr; // 缓冲区当前写入位置
char* _IO_write_end; // 缓冲区写入结束位置
char* _IO_buf_base; // 缓冲区基地址(若使用自定义缓冲区)
char* _IO_buf_end; // 缓冲区结束地址
struct _IO_FILE* _chain; // 链表指针(用于关联多个打开的文件)
int _fileno; // 底层文件描述符(Linux 中文件的唯一标识,如 0=stdin、1=stdout、2=stderr)
int _err; // 错误码(记录文件操作错误)
int _eof; // EOF 标志(非0表示已到达文件末尾)
// 其他成员:缓冲区大小、编码格式、锁机制等...
} FILE;
在这个结构体中,有2个属性重要一些,读写缓冲区和文件描述符。
缓冲区
缓冲区——文件内核缓冲区和用户文件缓冲区
用户文件缓冲区
用户文件缓冲区存在于C标准库中——存在于FILE中。如下图所示。
用户文件缓冲区的刷新策略
-
无策略,直接刷新。
-
行刷新,遇到'\n'(适用于显示器)。
-
满刷新。
两种情况
-
进程退出,直接刷新。
-
fflush强制刷新。
文件内核缓冲区
文件被打开后,OS会先创建这个文件的struct file结构体,然后在内存中再为这个文件创建三个空间,来存储这个文件的相关信息。文件属性,读写方法和文件内核缓冲区。如下图所示。

文件描述符
-
C库中的文件操作函数,都是对系统函数的封装。在上层C库中,我们打开一个文件就会返回一个FILE*的指针。其实,底层的函数会返回一个int型的数值,然后把这个数值返回给上层,上层再对这个数值进行封装——填充FILE的文件描述符属性,最后返回FILE*。
-
文件描述符就是一个普通的整形,它就是数组(文件描述符表)的下标。
-
底层返回整形,上层再对它进行封装,然后上层便可得到FILE*。
-
返回未被使用的最小的数组下标。
fd——>FILE*的过程代码如下所示:
struct IO_FILE
{
int flag; // 刷新⽅式
int fileno; // ⽂件描述符
char outbuffer[SIZE];
int cap;
int size;
// TODO
};
typedef struct IO_FILE mFILE;
mFILE *mfopen(const char *filename, const char *mode)
{
//。。。。。
fd = open(filename, O_RDONLY);
mFILE *mf = (mFILE*)malloc(sizeof(mFILE));
if(!mf)
{
close(fd);
return NULL;
}
mf->fileno = fd;
//mf->flag = FLUSH_LINE;
mf->size = 0;
mf->cap = SIZE;
return mf;
}
文件打开的全过程
如下图所示。
一个文件被打开,有两个人要知道,一个是OS,另一个就是进程本身。进程是自己的文件描述符表来知晓,而OS则进行双链表来管理。
链接
软链接
ln -s src dst
ln -s code.c code_soft
ubuntu@VM-4-17-ubuntu:~/review-linux/2026_1_12$ ls -l
total 4
drwxr-xr-x 2 ubuntu ubuntu 4096 Jan 12 11:09 A
-rw-r--r-- 1 ubuntu ubuntu 0 Jan 12 11:09 code.c
ubuntu@VM-4-17-ubuntu:~/review-linux/2026_1_12$ ln -s code.c code_soft
ubuntu@VM-4-17-ubuntu:~/review-linux/2026_1_12$ ll
total 12
drwxr-xr-x 3 ubuntu ubuntu 4096 Jan 12 11:09 ./
drwxr-xr-x 6 ubuntu ubuntu 4096 Jan 12 11:08 ../
drwxr-xr-x 2 ubuntu ubuntu 4096 Jan 12 11:09 A/
-rw-r--r-- 1 ubuntu ubuntu 0 Jan 12 11:09 code.c
lrwxrwxrwx 1 ubuntu ubuntu 6 Jan 12 11:09 code_soft -> code.c
ubuntu@VM-4-17-ubuntu:~/review-linux/2026_1_12$ vim code.c
ubuntu@VM-4-17-ubuntu:~/review-linux/2026_1_12$ cat code_soft
jjjjjj
-
文件内容里面存储的是被链接文件的路经。
-
相当于软件的快捷方式。
硬链接
ln src dst
ln code.c code_hard
ubuntu@VM-4-17-ubuntu:~/review-linux/2026_1_12$ ln code.c code_hard
ubuntu@VM-4-17-ubuntu:~/review-linux/2026_1_12$ ll
total 20
drwxr-xr-x 3 ubuntu ubuntu 4096 Jan 12 11:15 ./
drwxr-xr-x 6 ubuntu ubuntu 4096 Jan 12 11:08 ../
drwxr-xr-x 2 ubuntu ubuntu 4096 Jan 12 11:09 A/
-rw-r--r-- 2 ubuntu ubuntu 7 Jan 12 11:10 code.c
-rw-r--r-- 2 ubuntu ubuntu 7 Jan 12 11:10 code_hard
lrwxrwxrwx 1 ubuntu ubuntu 6 Jan 12 11:09 code_soft -> code.c
-
硬链接就是给被链接文件取“别名”==引用。
-
硬链接不能链接目录,否则就会出现路径解析死循环。
-
被硬链接指向的时候,被硬链接的文件,就会计数一下。
取消链接
对于软硬链接取消链接,指令:unlink 链接
unlink code_soft
ubuntu@VM-4-17-ubuntu:~/review-linux/2026_1_12$ ll
total 20
drwxr-xr-x 3 ubuntu ubuntu 4096 Jan 12 11:15 ./
drwxr-xr-x 6 ubuntu ubuntu 4096 Jan 12 11:08 ../
drwxr-xr-x 2 ubuntu ubuntu 4096 Jan 12 11:09 A/
-rw-r--r-- 2 ubuntu ubuntu 7 Jan 12 11:10 code.c
-rw-r--r-- 2 ubuntu ubuntu 7 Jan 12 11:10 code_hard
lrwxrwxrwx 1 ubuntu ubuntu 6 Jan 12 11:09 code_soft -> code.c
ubuntu@VM-4-17-ubuntu:~/review-linux/2026_1_12$ unlink code_soft
ubuntu@VM-4-17-ubuntu:~/review-linux/2026_1_12$ ll
total 20
drwxr-xr-x 3 ubuntu ubuntu 4096 Jan 12 11:21 ./
drwxr-xr-x 6 ubuntu ubuntu 4096 Jan 12 11:08 ../
drwxr-xr-x 2 ubuntu ubuntu 4096 Jan 12 11:09 A/
-rw-r--r-- 2 ubuntu ubuntu 7 Jan 12 11:10 code.c
-rw-r--r-- 2 ubuntu ubuntu 7 Jan 12 11:10 code_hard
路径解析死循环问题
硬链接不能链接目录,只能链接普通文件,而软连接可以链接目录/普通文件。
原因:
路径解析不是看文件名解析的,而是看文件的inode进行路径解析的。举个例子,当A目录里面--->有个子目录B,B目录里面有个硬链接C,C链接到B目录。当执行cd A/B/C,就会出现路径回环问题,死循环。如下图所示。
而软链接就不会出现这种情况,因为软连接是个独立的文件,有自己的inode,假设C软链接到B,它里面存的是被链接文件的路径,所以,当解析的C时,会继续解析C里面的路径,就会解析到B文件,就会停止了。
动静态库
动静态库的分类
Windows:.lib是静态库,.dll是动态库。
Linux:.a是静态库,.so是动态库。
静态库
静态最终会被拷贝一份到代码中,所以最终的代码可以脱离静态库,独立运行。
静态库的生成
指令:ar -rc $@ $^,如下所示的Makefile文件。
libmyadd.a:add.o sub.o
ar -rc $@ $^ #生成静态库
%.o:%.c
gcc -c $<
.PHONY:clean
clean:
rm -rf code.exe test.o add.o sub.o
静态库的固定格式
格式:lib + 自己命名+.a
静态库的使用
gcc/g++编译器,都是默认进行系统查找对应的库,而是我们自己生成的库,需要使用如下的指令。
-L:指定库的路径。
-l:指定链接的库。
如下所示的使用方式。指令:gcc main.c -L. -lmyadd
ubuntu@VM-4-17-ubuntu:~/review-linux/2026_1_20/code$ gcc main.c -L. -lmyadd
ubuntu@VM-4-17-ubuntu:~/review-linux/2026_1_20/code$ ./a.out
6
4
#表示,告诉编译器,我要链接.当前目录下的myadd库。
-l链接库的时候,去掉库的前缀和后缀,只链接库即可。
动态库
动态库不会加载到代码里面,代码会运行时查找动态库。
动态库的生成
-
生成.o文件:
gcc-fpic-c $<。 -
生成动态库:
gcc -o $@ $^-shared,如下所示的Makefile文件。
libmysub.so:sub.o add.o
gcc -o $@ $^ -shared
%.o:%.c
gcc -fpic -c $<
.PHONY:clean
clean:
rm -rf code.exe test.o add.o sub.o
动态库的固定格式
格式:lib + 自己命名+.so
动态库的使用
如下所示的使用方式。指令:gcc main.c -L. -lmyadd
对于动态库的运行,直接运行的话,会报错,需要把动态库放在系统指定的路径下,才会运行成功。
头文件
对于"add.h"的形式,直接编译运行即可。但是,对于<add.h>,编译的时候要指名头文件。指令:-I
ubuntu@VM-4-17-ubuntu:~/review-linux/2026_1_20/code$ gcc main.c -I. -L. -lmyadd
ubuntu@VM-4-17-ubuntu:~/review-linux/2026_1_20/code$ ./a.out
6
4
总结
-
动静态库的格式基本一致,除了后缀不一样。
-
两者进行编译的时候,都需要指名要链接的库,gcc main.c -L. -lmyadd
-
注意生成动静态库的指令。
-
动态库的运行的时候,需要把动态库拷贝到系统指定的库路径中,才能运行。
ubuntu@VM-4-17-ubuntu:/usr/lib$ sudo ln -s /home/ubuntu/review-linux/2026_1_20/code/libmysub.so libmysub.so
ubuntu@VM-4-17-ubuntu:/usr/lib$ ll
total 1084
drwxr-xr-x 91 root root 4096 Jan 21 16:22 ./
drwxr-xr-x 14 root root 4096 Apr 21 2022 ../
drwxr-xr-x 2 root root 4096 Oct 24 2024 apparmor/
drwxr-xr-x 5 root root 4096 May 13 2025 apt/
drwxr-xr-x 2 root root 4096 May 18 2022 bfd-plugins/
drwxr-xr-x 2 root root 4096 Nov 27 2024 binfmt.d/
drwxr-xr-x 3 root root 4096 Apr 21 2022 byobu/
drwxr-xr-x 2 root root 4096 Dec 1 2022 cloud-init/
-rwxr-xr-x 1 root root 1075 Dec 8 2021 cnf-update-db*
-rwxr-xr-x 1 root root 3565 Dec 8 2021 command-not-found*
drwxr-xr-x 2 root root 4096 May 14 2025 compat-ld/
drwxr-xr-x 2 root root 4096 Apr 21 2022 console-setup/
lrwxrwxrwx 1 root root 21 May 18 2022 cpp -> /etc/alternatives/cpp*
drwxr-xr-x 3 root root 4096 May 18 2022 crash/
drwxr-xr-x 2 root root 4096 Apr 24 2022 crda/
drwxr-xr-x 4 root root 4096 Apr 21 2022 cryptsetup/
drwxr-xr-x 5 root root 4096 Dec 11 17:12 cups/
drwxr-xr-x 2 root root 4096 Dec 1 2022 dbus-1.0/
drwxr-xr-x 3 root root 4096 Dec 12 16:12 debug/
drwxr-xr-x 3 root root 4096 Apr 21 2022 dpkg/
drwxr-xr-x 3 root root 4096 Apr 21 2022 dracut/
drwxr-xr-x 2 root root 4096 Sep 18 2024 environment.d/
drwxr-xr-x 2 root root 4096 Oct 7 2023 file/
drwxr-xr-x 2 root root 4096 Apr 21 2022 finalrd/
drwxr-xr-x 85 root root 24576 Apr 24 2022 firmware/
drwxr-xr-x 3 root root 4096 May 18 2022 gcc/
drwxr-xr-x 2 root root 4096 Apr 21 2022 girepository-1.0/
drwxr-xr-x 3 root root 24576 Aug 1 19:43 git-core/
drwxr-xr-x 2 root root 4096 Sep 23 2022 gnupg/
drwxr-xr-x 2 root root 4096 Sep 23 2022 gnupg2/
drwxr-xr-x 2 root root 4096 May 14 2025 gold-ld/
drwxr-xr-x 4 root root 4096 Apr 21 2022 groff/
drwxr-xr-x 3 root root 4096 Apr 24 2022 grub/
drwxr-xr-x 2 root root 4096 Apr 24 2022 grub-legacy/
drwxr-xr-x 2 root root 4096 Apr 21 2022 hdparm/
drwxr-xr-x 2 root root 4096 Apr 21 2022 init/
drwxr-xr-x 3 root root 4096 Apr 21 2022 initcpio/
drwxr-xr-x 4 root root 4096 Apr 21 2022 initramfs-tools/
drwxr-xr-x 3 root root 4096 Apr 21 2022 kernel/
drwxr-xr-x 3 root root 4096 Apr 21 2022 klibc/
-rwxr-xr-x 1 root root 78784 Apr 13 2024 klibc-BnzSoOUNgFnGkEcRdekugdBENMs.so*
lrwxrwxrwx 1 root root 16 Oct 29 2022 libdmmp.so -> libdmmp.so.0.2.0
-rw-r--r-- 1 root root 38984 Oct 29 2022 libdmmp.so.0.2.0
lrwxrwxrwx 1 root root 18 Feb 9 2022 libhandle.so.1 -> libhandle.so.1.0.3
-rw-r--r-- 1 root root 14520 Feb 9 2022 libhandle.so.1.0.3
lrwxrwxrwx 1 root root 16 Oct 29 2022 libmpathcmd.so -> libmpathcmd.so.0
-rw-r--r-- 1 root root 14408 Oct 29 2022 libmpathcmd.so.0
lrwxrwxrwx 1 root root 20 Oct 29 2022 libmpathpersist.so -> libmpathpersist.so.0
-rw-r--r-- 1 root root 38984 Oct 29 2022 libmpathpersist.so.0
lrwxrwxrwx 1 root root 17 Oct 29 2022 libmultipath.so -> libmultipath.so.0
-rw-r--r-- 1 root root 409672 Oct 29 2022 libmultipath.so.0
lrwxrwxrwx 1 root root 52 Jan 21 16:22 libmysub.so -> /home/ubuntu/review-linux/2026_1_20/code/libmysub.so*
drwxr-xr-x 3 root root 4096 Apr 24 2022 linux/
drwxr-xr-x 3 root root 4096 Apr 24 2022 linux-boot-probes/
drwxr-xr-x 3 root root 4096 Jul 1 2025 locale/
drwxr-xr-x 4 root root 4096 Dec 11 17:12 lsb/
drwxr-xr-x 2 root root 4096 Apr 21 2022 man-db/
drwxr-xr-x 2 root root 4096 Sep 1 12:08 mecab/
drwxr-xr-x 3 root root 4096 Aug 30 2021 mime/
drwxr-xr-x 2 root root 4096 Jul 1 2025 modprobe.d/
drwxr-xr-x 3 root root 4096 Jul 1 2025 modules/
减少编译时的指令方法:
-
可以把动静态库分别拷贝到系统指定的库文件中——可以搞个软连接。
-
可以把动静态库路径放在系统环境变量中。
-
也可以放在系统环境配置文件中——bashrc。
更多推荐





所有评论(0)