软硬链接
软硬连接的本质区别:有没有独立的inode。
软连接有独立的inode ->软连接是一个独立的文件
应用、相当于windows下的快捷方式
特性:可以理解成为:软连接的文件内容,是指向的文件对应的路径!
硬链接没有独立的inode->硬链接不是一个独立的文件
创建硬链接,不是真正的创建新文件
创建硬链接,究竟做了什么呢?
就是在指定的目录下,建立了文件名和指定inode的映射关系—--仅此而已!
[hang@VM-4-12-centos day7]$ cd tmp [hang@VM-4-12-centos tmp]$ touch test1 [hang@VM-4-12-centos tmp]$ touch test2 [hang@VM-4-12-centos tmp]$ ln -s test1 soft.link [hang@VM-4-12-centos tmp]$ ls -l total 0 lrwxrwxrwx 1 hang hang 5 Nov 1 10:08 soft.link -> test1 -rw-rw-r-- 1 hang hang 0 Nov 1 10:07 test1 -rw-rw-r-- 1 hang hang 0 Nov 1 10:07 test2
软链接是
ln -s 被链接的文件 新的文件
硬链接
[hang@VM-4-12-centos tmp]$ ls -l total 0 lrwxrwxrwx 1 hang hang 5 Nov 1 10:08 soft.link -> test1 -rw-rw-r-- 1 hang hang 0 Nov 1 10:07 test1 -rw-rw-r-- 1 hang hang 0 Nov 1 10:07 test2 [hang@VM-4-12-centos tmp]$ ln test2 link [hang@VM-4-12-centos tmp]$ ls -l total 0 -rw-rw-r-- 2 hang hang 0 Nov 1 10:07 link lrwxrwxrwx 1 hang hang 5 Nov 1 10:08 soft.link -> test1 -rw-rw-r-- 1 hang hang 0 Nov 1 10:07 test1 -rw-rw-r-- 2 hang hang 0 Nov 1 10:07 test2
硬链接
ln 被链接的文件 新的文件
硬链接涉及到了一个引用计数,
以下面的这段代码为例
[hang@VM-4-12-centos day12]$ ln test1 exe [hang@VM-4-12-centos day12]$ ls -il total 0 790180 -rw-rw-r-- 2 hang hang 0 Feb 11 20:10 exe 790180 -rw-rw-r-- 2 hang hang 0 Feb 11 20:10 test1 790181 -rw-rw-r-- 1 hang hang 0 Feb 11 20:10 test2
上面的数字是2,因为同一个inode编号被两个文件名使用。
那么有什么用?? ?可以不进入一个目录就大概知道里面有多少目录。
因为目录本身的文件名就是一个引用计数,然后就是目录里面的 . 这就是两个引用计数了。若是有其他目录,那么就会存在 .. 这个引用计数了。
默认创建目录,引用计数(硬链接)为何是2?是因为:自己目录名; inode
自己目录内部: . inode
动静态库
静态库 ,他这个库中是没有main函数的。
那么我们形成一个库,include(库的所有头文件)一 lib(对应的库文件)
头文件gcc的默认搜索路径是:/usr/include 库文件的默认搜索路径是:/lib64 or /usr/lib64
我们刚刚的拷贝库到系统的默认路径下,就叫做库的安装
静态库
makefile
libmytmpself.a:mymath.o myprint.o ar -rc libmytmpself.a mymath.o myprint.o mymath.o:mymath.c gcc -c mymath.c -o mymath.o myprint.o:myprint.c gcc -c myprint.c -o myprint.o .PHONY:mytmpself mytmpself: mkdir -p mytmpself/include mkdir -p mytmpself/lib cp -rf *.h mytmpself/include cp -rf *.a mytmpself/lib .PHONY:clean clean: rm -rf *.o libmytmpself.a mytmpself
注意的是库的名称是有规范的
是 lib___.a。中间既是文件名。
[hang@VM-4-12-centos day7]$ tree . . |-- mklib | |-- libmytmpself.a | |-- Makefile | |-- mymath.c | |-- mymath.h | |-- mymath.o | |-- myprint.c | |-- myprint.h | |-- myprint.o | `-- mytmpself | |-- include | | |-- mymath.h | | `-- myprint.h | `-- lib | `-- libmytmpself.a `-- uselib |-- a.out |-- main.c |-- my.exe `-- mytmpself |-- include | |-- mymath.h | `-- myprint.h `-- lib `-- libmytmpself.a 8 directories, 17 files
将自己的代码放到库中进行编译(不建议)
593 2022-11-01 09:18:38 sudo cp mytmpself/include/* /usr/include/ -rf 596 2022-11-01 09:19:55 sudo cp -rf mytmpself/lib/libmytmpself.a /lib64
不将自己的代码放到库中
gcc main.c -I ./mytmpself/include/ -L./mytmpself/lib/ -lmytmpself
动态库
makefile
.PHONY:all all:libhello.so libhello.a libhello.so:mymath_d.o myprint_d.o gcc -shared mymath_d.o myprint_d.o -o libhello.so mymath_d.o:mymath.c gcc -c -fPIC mymath.c -o mymath_d.o myprint_d.o:myprint.c gcc -c -fPIC myprint.c -o myprint_d.o libhello.a: mymath.o myprint.o ar -rc libhello.a mymath.o myprint.o mymath.o:mymath.c gcc -c mymath.c -o mymath.o myprint.o:myprint.c gcc -c myprint.c -o myprint.o .PHONY:output output: mkdir -p output/lib mkdir -p output/include cp -rf *.h output/include cp -rf *.a output/lib cp -rf *.so output/lib .PHONY:clean clean: rm -rf *.o *.a *.so output
如何理解动态库?
静态库的话,就是相当于硬编码就进入了我们的代码区。
而动态库的话,就相当于原来的代码正常运行,然后呢需要库的的时候,把它加载到堆栈的共享区,在这个过程中,我们的的动态库当然也加载到内存中了。如果其他进程需要调用这个静态库的话,可以直接调用,不用加载了。而静态库的话,就必须在加载一次(内存中又多了一份一摸一样的东西),下面还有讲解。
每一个动态库被加载到内存,映射到进程的地址空间,映射的位置可能是不一样的但是因为库里面是相对地址,每一个函数定位采用的是偏移量的方式找的
换句话说,只要知道这个库的相对地址,库的起始地址+函数偏移量=就可以在自己的地址空间中访问库中的所有函数了,只要你有访问的话
新的gcc标记
gcc -fPIC //后面就正常弄就可以了
这个有什们意义呢?
gcc -fPIC -c mymath.c -o mymath.o
生成一个位置无关的二进制文件,怎么理解呢??
如果我们生成了一个库,势必要编译到到我们的可执行程序中去,可是我们的可执行程序是有自己的地址空间的,那么在这过程中,我们的库只能加载到地址空间的特定位置上,而我们动态库不需要加载到特定的地址空间,
[hang@VM-4-12-centos mklib]$ ls -l total 20 -rw-rw-r-- 1 hang hang 371 Nov 6 20:25 Makefile -rw-rw-r-- 1 hang hang 261 Nov 6 20:25 mymath.c -rw-rw-r-- 1 hang hang 75 Nov 6 20:25 mymath.h -rw-rw-r-- 1 hang hang 105 Nov 6 20:25 myprint.c -rw-rw-r-- 1 hang hang 88 Nov 6 20:25 myprint.h
然后通过上面的生成对应的与位置无关的二进制文件,
gcc -fPIC -c mymath.c -o mymath.o gcc -fPIC -c myprint.c -o myprint.o
接下来怎样生成动态库呢?
是这样的吗?
gcc mymath.o myprint.o -o liboutput.so
实践证明是不可以的,提示我们没有main函数。因为操作系统分不清,我们是要生成一个动态库,还是一个可执行程序,所以应该这样写
gcc -shared mymath.o myprint.o -o liboutput.so
加一个 -shared ,这样才能生成动态库。
注意的是库的名称是有规范的
是 lib___.so。中间既是文件名。
,a.如果我们只有静态库,没办法,gcc只能针对该库进行静态链接
b.如果动静态库同时存在,默认用的就是动态库。
-static的意义:摒弃默认优先使用动态库的原则,而是直接使用静态库的方案!
使用动态库的方案。
- 就是把 动态库拷贝到 库路径底下。
ls /64lib
- 环境变量的方法
[hang@VM-4-12-centos day12]$ LD_LIBRARY_PATH [hang@VM-4-12-centos day12]$ echo $LD_LIBRARY_PATH :/home/hang/.VimForCpp/vim/bundle/YCM.so/el7.x86_64
[hang@VM-4-12-centos day12]$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:库所在的路径 此时需要注意的是路径不用带那个库
- 解决环境变量
[hang@VM-4-12-centos day12]$ ls /etc/ld.so.conf.d/ bind-export-x86_64.conf dyninst-x86_64.conf kernel-3.10.0-1160.71.1.el7.x86_64.conf mariadb-x86_64.conf
在这个目录下创建一个.conf的配置文件。然后呢,就是vim打开,然后把库的路径直接拷贝进去,然后ldconfig更新一下(让配置文件生效一下),就行了。
- 发士
ln -s 库目录(绝对路径) /lib64/文件名
在库目录,建立了一个软连接