Linux:软硬连接和动静态库

news2024/11/13 8:55:16

一般ll一下,最左边一列就是文件类型:

怎么创建链接文件:

ln -s 目标文件 创建的链接文件名

来试试:这叫软连接,软连接相当于Windows下的快捷方式,直接指向原文件的绝对路径;删除软连接不影响原文件

什么是硬链接?

创建硬链接

ln file_target2.txt file_hard.link

硬链接在Linux下相当于备份了一份对应文件

我们可以查看他们的inode来看他们的本质区别:

可以发现软连接的inode和原文件的inode是不一样的,但是硬链接的inode和原文件的inode是一样的

硬链接是通过文件的inode来引用原文件,软连接是通过文件的文件名来引用文件

为什么硬链接的inode和原文件的inode一样?

这个一样的inode其实起到的是一个映射的作用,建立一个新的硬链接就是代表了一串数字可以映射两个文件,指针指向同一个文件属性,指针计数为2

什么是指针计数?

这就是指针计数

我们可以看出:目录新建时都是两个指针计数,如果在目录内建立一个目录,计数+1,目录内再每有一个目录,计数-2

Linux下的.和..目录比较特殊,.表示当前目录,..表示上一级目录,这两个文件名是固定,所有系统和指令在使用时都预先知道他们的作用,你删除也是删除不了的(毕竟你无法删除你所在的目录)

硬链接一般都用作文件备份

打开的文件与内核、内存有关

没打开的文件和文件系统、磁盘有关

我们在向文件写入时可以使用两种方法:

int a=114514//二进制写入
114514 > "114514"//文本写入

动态库和静态库

我们之前在学习编译的过程的时候,第四步的库的链接就分为动态库和静态库

查看你的可执行程序对应的库:

ll查看一下我们的标准库

我们写一个c++的文件来看一下c++的标准库:

#include<iostream>
#include<string>
int main(){
    std::string name="hahaha";
    std::cout<<name<<std::cout endl;
    return 0;
}

查看依赖的库:

ldd 可执行程序文件名

后缀是.a的库是静态库,.so是动态库

愿意为你动态库是系统通过接口调用的,所以原则上是大家共用的

Windows的动态库的后缀是.dll和.lib

我们也可以通过file命令查看库的类型:

dynamically linked动态链接

回顾编译的四个步骤:

1.预处理:引入头文件,去注释,宏替换,条件编译。以#开头的属于预处理指令部分,例如#define,#if,#include,产生.i文件,指令:gcc -E mytest.c -o test.i

2.编译:完成语法和语义分析,生成汇编代码。此阶段可以检测到语义错误和语法错误,还有变量未定义的行为,指令:gcc -S test.i -o test.s

3.汇编:将汇编代码翻译为机器码指令,也就是二进制文件,文件格式是.o文件,指令:gcc -c test.s - o test.o

4.链接:完成文件中调用的函数跟静态库或动态库的链接,并将他们打包合并形成可执行文件:gcc test.o -o test

从上述四个过程中可以看出:只有.o文件,才涉及到库的事情,我们要使用自己制作的库或者链接别人的库,只要对这个.o文件链接就好了

一个可执行文件在运行前,里面的机器码由操作系统从磁盘上的动态库中复制到内存中,这个过程叫动态链接;操作系统采用虚拟内存机制允许物理内存中的动态库被其他进程使用,节省磁盘空间。

库的真实名字是:去掉前面lib前缀,去掉.a或.so后缀之后剩下的部分

库的制作和使用:

库是一个二进制文件,想使用库一定由三个部分组成:库文件,头文件,文档说明

库文件:函数的定义

头文件:函数的声明

我们来制作一个静态库:

//add.h
#pragma once
#include <stdio.h>
extern int my_add(int x, int y); 
//add.c
#include "add.h" 
int my_add(int x, int y) {
     return x + y;                                                 
}
//sub.h
#pragma once
#include <stdio.h>
extern int my_sub(int x, int y); 
//sub.c
#include "sub.h"                                                   
int my_sub(int x, int y){
    return x - y;
}

.h文件里的#pragma once的作用是防止该文件被多次引用,宏定义不会和其他定义冲突

#ifndef起到的作用和#pragma once 类似,但是前者的连内容相同的文件也可以不同时包含,缺点是宏定义如果有重复的时候也会被过滤掉

#indef是受c/c++语言标准库支持的,而#pragmat once 是编译器支持的,有的编译器肯不支持这样使用

1.静态库的制作:

我们得先有一个自己的.o文件:

然后我们要打包

使用我们的打包命令:

ar -rc libmymath.a add.o sub.o

ar是gnu的归档工具,将目标文件打包为静态库
-c(create):建立静态库文件

-r(replace):若静态库的目标文件有更新,则用新的替换旧的

ar命令也可以用来查看静态库中的文件:

ar -tv libmymath.a 

-t:列出静态库中的文件

-v:显示详细信息

发布静态库

我们的静态库要供人使用,除了.o文件以外,还要把头文件也发布出去:

创建一个output目录->把库文件和头文件一起放进去

cp -rf libmymath.a output/
cp *.h output/
*是一个通配符,上述命令的意思为复制所有以.h结尾的文件

上述的步骤我们也可以通过写一个makefile,来集成操作:

Makefile:
libmymath.a:sub.o add.o
	ar -rc $@ $^

%.o:%.c
	gcc -c $<

.PHONY:output
output:
	mkdir output
	cp -rf *.h output
	cp libmymath.a output

我的已经是最新的所以up to date

静态库的使用:

方法一:

我们创建一个新目录:

mkdir friend

在里面写一个程序:

#include "add.h"
#include "sub.h"
int main() {
    int x = 30;
    int y = 20;
    int ret1 = my_add(x, y);
    int ret2 = my_sub(x, y);
    printf("ret1 = %d\n",ret1);
    printf("ret2 = %d\n",ret2);
    return 0;
}

来编译一下:

我们发现失败了,原因是缺少头文件add.h

因为编译器在编译时会在当前目录下的文件中寻找库,但是我们这个目录下只有mytest.c:

所以我们需要告诉编译器,库文件在那个目录下,需要给出路径:

gcc mytest.c -I /home/name/test

又报上错了。。为什么呢?

我们只告诉编译器头文件,还没告诉它库文件在哪

所以应该:gcc mytest.c -I /home/name/test -L /home/name/test -l mymath

格式是:

gcc 你的c程序 -I 头文件路径 -L 库文件路径 -l 库文件名称
  • -I(大写i):指定头文件所在路径。
  • -L:指定库文件所在路径。
  • -l(小写l):指明需要链接库文件路径下的哪一个库

这里也可以写成makefile:

mytest.out:mytest.c
	 gcc -o $@ $^ -I /home/name/test -L /home/name/test -l mymath
.PHONY:clean
clean:
	rm -f mytest

方法二:将我们做的库放到系统默认的库的路径下,这样以前怎么编译,现在怎么编译

制作动态库:

gcc -shared -o libmymath.so add.o sub.o

-shared:Linux在gcc编译时加上-shared参数时,使源码编译成动态库文件.so

发布动态库:

我们可以把这些库文件头文件全部打包起来(其实静态库也需要这么干):

如果是makefile是这么写:

libmymath.so:add.o sub.o
	gcc -shared -o $@ $^
%.o:%.c
	gcc -fPIC -c $<
.PHONY:clean
clean:
	rm -rf libmymath.so *.o lib
.PHONY:lib
lib:
	mkdir lib
	cp *.h lib
	cp libmymath.so lib

动态库的使用:

和静态库一样但略有区别

 gcc mytest.c -I /home/name/test/lib -L /home/name/test/lib -l mymath

如果按静态库的使用方法你会发现能编译但不能运行

我们ldd一下发现库这里写的not found

为什么呢?

因为编译的时候是编译器负责,执行的时候是加载器完成,我们需要在运行的时候告诉系统库文件在哪里

1.把我们自己库文件拷贝到默认路径/usr/lib,这里不做演示

2.更改LD_LIBRARY_PATH

export LD_LIBRARY_PATH=/home/name/test/lib

LD_LIBRARY_PATH环境变量用于在程序加载运行期间查找动态链接库时指定除了系统默认路径之外的其他路径。注意,LD_LIBRARY_PATH中指定的路径会在系统默认路径之前进行查找

再次ldd查看:

欸,为什么还是不行?

别着急,更新一下缓存

 sudo ldconfig /home/name/test/lib

大概就是这样啦

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2116127.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

通义千问大模型Java调用,百炼

文章目录 一、大模型服务平台[百炼](https://help.aliyun.com/zh/model-studio/getting-started)二、Java sdk调用与eventStream三、百炼平台其它 一、大模型服务平台百炼 百炼是阿里新出的一个大模型服务平台&#xff0c;聚合了多个千问大模型及其它一些大模型的调用&#xf…

【MySQL】Ubuntu22.04安装MySQL8.0.39及修改默认用户名和密码

文章目录 安装mysql1. 下载mysql2. 查看mysql版本3. 启动mysql服务&#xff08;通常在安装后自动启动&#xff09;4. 运行安全配置脚本 修改用户名和密码1. 查看mysql自动设置的随机账号与密码2. 用默认账号密码登录mysql3. 找到账号密码有关的数据库4. 更改用户名和密码mysql5…

C++:AVL树保姆级详解

目录 AVL树概念 AVL树的性质 AVL树节点定义 AVL树的构造函数和拷贝函数 构造函数 拷贝构造 AVL树的插入(灰常重要) 更新平衡因子 什么时候向上调整平衡因子 如何向上调整平衡因子 旋转 左单旋 右左单旋 右单旋 左右单旋 AVL树的验证 验证是否是二叉搜索树 这…

Apollo星火计划基础速记

1 Apollo规划模块 规划根据感知预测的结果,当前定位信息以及Routing的结果,规划出一条安全行驶的轨迹送给控制模块 其中NaviPlanning主要用于高速公路的导航规划,OnLanePlanning用于城区及高速公路各种复杂车道;OpenSpacePlanning用于没有车道线的场景,主要在自主泊车和狭…

JavaDS —— 并查集

并查集概念 案例引入&#xff1a; 假设现在有三个程序设计小分队&#xff0c;分别来自广东&#xff0c;广西和海南&#xff0c;其中广东小分队人员的编号为{0&#xff0c;6&#xff0c;7&#xff0c;8} 广西小分队人员编号为{1&#xff0c;4&#xff0c;9}&#xff0c;海南小分…

关于WebZip乱码目录文件名修改

先引用一段 来描述问题&#xff1a; 在IT行业中&#xff0c;我们经常遇到与编码和字符集有关的问题&#xff0c;特别是在处理包含中文字符的文件或目录时。"WebZip乱码目录文件名修改"这个问题就是一个典型的例子&#xff0c;涉及到Webzip工具在下载包含中文路径的文…

清洁眼镜片

经常眼镜弄脏了 怎么弄都干净不了 根本无法佩戴 影响出门时间 有时在外很尴尬 其实清洁很简单 从水龙水冲洗镜片(可附上洗手液) 然后用纸巾局部点触抹干偶尔泛起小水滴 就好

计算机毕业设计SpringBoot+VUE自动灌装生产线 MES 系统设计

采用 B/S 架构&#xff0c;MES 应用软件通过 TCP/IP 协议与自动灌装生产线上的各个工作单元中的 PLC 控制器进行通信&#xff0c;查询或采集由 PLC 控制器采集的生产数据。通过 JAVA 构建的平台与数据库进行连接&#xff0c;实现灌装生产线的生产管理、订单管理、质量管理和数据…

DPDK基础入门(六):从PCIe事务的角度看包处理

PCIe PCI Express&#xff08;Peripheral Component Interconnect Express&#xff09;又称PCIe&#xff0c;它是一种高速串行通信互联标准。PCIe规范遵循开放系统互联参考模型&#xff08;OSI&#xff09;&#xff0c;自上而下分为事务传输层、数据链路层、物理层。对于特定的…

【Hot100】LeetCode—70. 爬楼梯

目录 1- 思路动规五部曲 2- 实现⭐763. 划分字母区间——题解思路 3- ACM 实现 原题链接&#xff1a;70. 爬楼梯 1- 思路 动规五部曲 1- dp 数组创建&#xff0c;确定含义 dp[i] 代表到达 楼梯 i 的方法数 2- 状态转移方程 因为一共有两种移动的方式&#xff0c;当前 dp[i] …

基于Java的垃圾分类网站系统

你好呀&#xff0c;我是计算机学姐码农小野&#xff01;如果有相关需求&#xff0c;可以私信联系我。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot框架&#xff0c;B/S架构 工具&#xff1a;MyEclipse, Tomcat 系统展示 首页 用户管理…

Radmin-同一局域网只需IP就可以控制电脑

Radmin小编十多年前就在用&#xff0c;它是一款非常好用的局域网控制工具&#xff0c;可以完全替代Windows自带的远程桌面&#xff0c;它的安全性和便于操作性都比Windows的远程桌面好用。 Radmin还有一个好处&#xff0c;就是远程别人电脑时&#xff0c;对方那边毫无察觉&…

明明的随机数处理问题分析与解决方案

明明的随机数处理问题分析与解决方案 引言问题描述解决方案数据结构设计具体步骤伪代码C语言实现详细解释读取输入去重操作排序操作输出结果复杂度分析引言 明明生成了N个1到500之间的随机整数,我们需要对这些整数进行处理,删去重复的数字,然后进行排序并输出结果。本文将详…

【JavaScript】LeetCode:16-20

文章目录 16 无重复字符的最长字串17 找到字符串中所有字母异位词18 和为K的子数组19 滑动窗口最大值20 最小覆盖字串 16 无重复字符的最长字串 滑动窗口 哈希表这里用哈希集合Set()实现。左指针i&#xff0c;右指针j&#xff0c;从头遍历数组&#xff0c;若j指针指向的元素不…

jmeter性能测试HTML测试报告生成详解

作用&#xff1a;jmeter支持生成HTML测试报告&#xff0c;方便查看测试计划中获得图表和统计信息 命令&#xff1a; jmeter -n -t [jmx file] -l [result file] -e -o [html report folder] 示例&#xff1a;jmeter -n -t login.jmx -l result.jtl -e -o ./report jmx文件&a…

玛雅Maya2024下载安装教程影视三维3D设计教程百度网盘分享链接地址

玛雅Maya下载安装教程影视三维3D设计教程百度网盘分享链接地址,玛雅是一款3d设计软件。Maya 是由 Autodesk 公司开发的专业三维计算机图形软件。主要应用于影视特效制作、游戏开发、广告设计和工业设计等领域。在影视特效中&#xff0c;可创建逼真特效场景和角色动画&#xff1…

【Day09-IO-字符流其它流】

IO流 IO流-字符流 字节流&#xff1a;适合复制文件等&#xff0c;不适合读写文本文件 字符流&#xff1a;适合读写文本文件内容 FileReader&#xff08;文件字符输入流&#xff09; 作用&#xff1a;以内存为基准&#xff0c;可以把文件中的数据以字符的形式读入到内存中来。 …

husky 工具配置代码检查工作流:提交代码至仓库前做代码检查

提示&#xff1a;这篇博客以我前两篇博客作为先修知识&#xff0c;请大家先去看看我前两篇博客 博客指路&#xff1a;前端 ESlint 代码规范及修复代码规范错误-CSDN博客前端 Vue3 项目开发—— ESLint & prettier 配置代码风格-CSDN博客 husky 工具配置代码检查工作流的作…

高并发内存池(二):​整体框架的介绍与ThreadCache的实现

目录 整体框架介绍 ThreadCache的主体框架 自由链表-FreeList 内存对齐-RoundUp 计算桶位置-Index 基础版 进阶版 线程局部存储 __declspec(thread) 关键字 实现线程无锁 申请内存-Allocate 释放内存-Deallocate 从中心缓存中申请内存 整体框架介绍 高并发内存池…

变量数据类型 Day3

1. 变量 1.1 变量的概念 变量是计算机内存中的一块存储单元&#xff0c;是存储数据的基本单元变量的组成包括&#xff1a;数据类型、变量名、值&#xff0c;后文会具体描述变量的本质作用就是去记录数据的&#xff0c;比如说记录一个人的身高、体重、年龄&#xff0c;就需要去…