重定向
重定向的符号
“>”:清空重定向
“>>”:追加重定向
从内核角度理解重定向
在进程的结构体中,有一个描述进程打开文件的信息的结构体指针(struct file_struct *files;),该结构体指针指向一个结构体(struct file _struct{…}),这个结构体里面有一个结构体(struct file * fd_array[NR_OPEN_DEFAULT]),该结构体保存一个指针数组,可以理解为一个文件描述符表,里面保存的是当前进程打开文件的信息,我们所说的文件描述符就是该指针数组的下标,该指针数组里面保存的指针变量是一个结构体指针(struct file *),该指针指向一个结构体(struct file{…}),这个结构体是描述文件具体信息的。
重定向就是将struct file *这个结构体指针的指向改变成为另外一个struct file结构体。也就是说,从指向某一个文件改变为指向另一个文件。
重定向的接口dup2函数
函数原型:
int dup2(int oldfd, int newfd);
作用:将newfd的值重定向为oldfd,即newfd拷贝oldfd
参数:newfd和oldfd都是文件描述符
执行成功:第一关闭newfd,让newfd指向oldfd对应的struct file*结构体
执行失败:1、如果oldfd是一个非法或者是无效的文件描述符,则重定向失败,newfd没有变化;2、如果oldfd和newfd的值相等,则什么事情都不干。
代码验证:
将标准输出重定向为a.txt文件。
#include <stdio.h>
2 #include <unistd.h>
3 #include <fcntl.h>
4 int main()
5 {
6 //让标准输出流指向a.txt文件
7 int fd =open("./a.txt",O_RDWR | O_CREAT,0664);
8 if(fd < 0){
9 perror("fopen");
10 return 0;
11 }
12
13 printf("before dup2:hello world\n");
14
15 /*
16 * oldfd:fd
17 * newfd:1 将一号标准输出重定向到fd对应的文件
18 * 1 要进行指向更新
19 */
20 dup2(fd,1);
21 printf("after dup2:hello world.\n");
22 return 0;
23 }
动态库和静态库
静态库和动态库都是文件,称之为库文件,用来保存程序代码,在编译一个程序的时候,所链接的库都是独立进行编译的,所以库文件可以将代码分模块出来,哪个模块有问题就修改哪个模块。
什么是库?静态库和动态库都是程序代码的集合。一般为了方便将程序提供给第三方使用,就是将程序编写成为库文件提供给第三方使用,优点首先就是不会泄漏公司的源码,其次就是调用者不用关心库文件内部实现,只需要关注如何调用即可。
动态库
特征:
- Windows系统下:没有前缀,后缀为dll
- Linux系统下:前缀为lib,后缀为.so
生成:
使用gcc/g++编译器,增加两个命令行参数:-fPIC和-shared,生成动态库的代码当中不需要包含main函数(程序入口函数)。
动态库的生成测试:
hello.h代码:
#pragma once
2 #include <stdio.h>
3
4 void PrintHello();
~
hello.c代码:
#include "hello.h"
2 void PrintHello(){
3 printf("exec hello.c:hello world.\n");
4 }
~
动态库的使用测试:
编译器在进行链接的时候找不到对应函数的实现,所以报错,编译终止。所以我们下面就得告诉编译器对应函数的实现在哪。
为了解决上面的问题,我们告诉了编译器依赖的动态库是哪一个,但是又出现了新的问题,编译器找不到动态库的路径,于是我们又说明了动态库的路径,所以在使用动态库的时候需要注意下面两点:
编译可执行程序的时候,依赖动态库。
-L[path]:指定动态库所在的路径
-l[动态库的名称,去掉前缀和后缀]:指定编译可执行程序时,依赖的动态库时哪一个。
现在我们就执行成功啦!完成了动态库的生成和动态库的使用的测试!
上面我们将mymain所依赖的动态库放到了可执行程序的路径下,可执行程序可以正常执行,但是如果我们将这个动态库从该路径移除呢?
mymain这个可执行程序已经不能执行了,原因是程序找不到动态库,那都有哪些方法可以解决这个问题呢?
- 将动态库放到可执行程序的路径下,不过不推荐
- 配置LD_LIBRARY_PATH,这个环境变量就是动态库的环境变量
- 放到系统库的路径下:/lib64,不过非常不推荐这样做
我们现在来解决一下上面这个问题,配置一下LD_LIBRARY_PATH这个环境变量。
静态库
特征:
- Windows系统下:没有前缀,后缀为.lib
- Linux系统下:前缀为lib,后缀为.a
生成:
- 第一阶段:使用gcc或者g++将源代码编译成为目标程序(.o)
- 第二阶段:使用ar -rc命令编译目标程序成为静态库
注意:如果直接使用源代码编译是不行的.
代码测试过程和动态库类似,注意命令不同,就不赘述了。
生成可执行程序的过程中需要依赖动态库或者静态库的时候,编译的时候一定要加上-l[库名]
软链接
软链接其实就是目标文件的快捷方式。
生成软链接:ln -s 源文件 软链接文件
注意事项:
修改软链接文件,源文件也会修改;
删除源文件的时候软链接文件内容会被清空。
源文件如果被删除,软链接文件还在的,如果修改软链接文件,那么会重新建立源文件,重新建立链接关系,所以删除源文件的时候,一定要将软链接文件也一起删除。
硬链接
硬链接是目标文件的替身。
生成硬链接:
ln 源文件 硬链接文件
硬链接的inode节点和源文件一致,软链接的inode节点和源文件不一致。