重定向
底层实现以及文件描述符的一些操作:
#include<stdio.h> #include<unistd.h> #include<fcntl.h> int main(){ //重定向,依赖操作系统的底层实现 //把本来输出到显示器的文件 输出到文件中 //这是重定向的底层实现:同样的文件描述符,这个描述符绑定到新的文件的时候,它不再输出到原来的文件中了,会输出到新的文件中,这个操作就叫重定向 close(1); int fd = open("test.txt", 0_WRONLY); fprintf(stderr, "fd=%d\n", fd); //fd = 1 //这两个输出语句等价 printf( "新的输出 %d\n", stdout->_fileno); //标准输出 没有显示到到显示器,显示到了文件中 fprintf(stdout, "新的输出 %d\n", stdout->_fileno); // stdout中始终是文件描述符 1 return 0; }
我们实现利用函数:dup2()
参数:old new
write vs printf
无缓冲区 vs 有缓冲区
//都会写到标准输出中 //输出到显示器上 printf("hehe\n"); //标准输出 fprintf(stdout, "haha\n"); //stdout 是char * //这两个带缓冲区的,加fork 结果就有两个 hehe 两个haha 因为子进程缓冲区有 write(1, "miaomiaomiao", strlen("miaomiaomiao")); //1是文件描述符 //无缓冲区,直接写到文件中 //fflush(stdout); //刷新缓冲区 fork();
动态链接库和静态链接库
动态链接库:把一些.c/.cpp文件生成一种特殊的二进制程序,自身不能直接执行,但是可以被其他可执行程序调用。
应用场景:游戏中最常见,客户端游戏更新,不用更新整个程序,而实更新其中的一部分模块,更新的就是动态链接库。
静态链接库:把一些.o文件打包到一起,生成一种特殊的二进制程序,自身不能直接执行,但是可以和.c文件编译生成一个新的可执行程序。这个新的可执行程序可以单独发布了。
应用场景:发布小程序的时候,可以只使用静态库的方式编译生成单独的可执行程序,不用依赖其他库,很方便。
平常链接实现:
//平常的链接 //在另一个文件add.c中 int add(int x, int y) { return x + y; } //新文件test.c #include<stdio.h> extern add(int x, int y); //函数声明 类似空头支票 //Maklefile 中不写 编译器就找不到,链接错误 //写了 就能找到,编译成功 int main() { int ret = add(10, 20); printf("%d\n", ret); return 0; } //Makefile 文件中 test:test.c add.c gcc $^ -o $@ //$^ 依赖
命名规则:
lib 前缀
.a 后缀(静态库)
.so 后缀(动态库)
静态库实现:
//静态库实现: //lib 前缀 //add 库名字 //.a 静态库 //.so 动态库 //依赖add.c文件 //Makefile文件中 生成静态库 libadd.a:add.c gcc -c add.c -o add.o // 先生成 .o 文件 ar - rc libadd.a add.o //把若干 .o 文件 打包成 .a //Makefile 文件中 test : test.c libadd.a gcc $^ -o $@ //$^ 依赖
上述执行结束,当前目录就会有 libadd.a 文件了。这件事就是静态库实现。
动态库实现:
//动态库实现: //lib 前缀 //add 库名字 //.a 静态库 //.so 动态库 //依赖add.c文件 //Makefile文件中 生成静态库 libadd.a:add.c gcc add.c -shared -fPIC libadd.so //Makefile 文件中 test : test.c libadd.so gcc $^ -o $@ //$^ 依赖
上述执行结束,当前目录就会有 libadd.so 文件了。这件事就是动态库实现。
ldd <文件名>:查看一个可执行程序依赖了多少动态库 (前面是小写L)
LD_LIBRARY_PATH:设定这个环境变量提醒系统区那些目录中查找动态库
动态库找不到的情况:
1.是否存在动态库
2.找不到就修改这个环境变量 LD_LIBRARY_PATH 就把动态库路径加进去
另外:libc.so 这个是包含了C语言所有标准库的东西,删了就重装系统吧~~~
在C++中的第三方库一般需要通过源码进行编译生成动态库或者静态库才能使用,但是由于编译环境的差异,编译过程出现问题的概率极大,这个过程极其痛苦。其他主流语言都是使用类似 yum 这样的包管理器来解决,最出名的:Python 的 pip ; JavaScript 的 nmp