Linux库概念及相关编程(动态库、静态库、环境变量)

分文件编程:

  • 好处:分模块编程思想,功能和责任划分清楚便与调试,main函数简洁,代码易于阅读。
  • 编程时头文件有的是使用<>这个符号括起来的,有的是" "使用的是双引号,使用尖括号括起来默认从/user/include/下面去找头文件或者是/user/local/include/下面去找,而使用双引号是默认从当前文件路径去找。

一个小栗子(两个数相加):

  • mainadd.c文件
#include<stdio.h>
#include"addfunc.h"
int main()
{int a,b,sum;printf("input first number:\n");scanf("%d",&a);printf("input second number:\n");scanf("%d",&b);sum=add(a,b);printf("sum is %d\n",sum);return 0;
}
  • addfunc.c文件,这个文件里面主要是函数体,函数的内部代码在这个文件里面写。
int add(int number1,int number2)
{int sum;sum=number1+number2;return sum;
}
  • addfunc.h文件代码,这个文件主要是函数的声明,addfunc.h这个文件在main函数头文件里面要被包含。
int add(int number1,int number2);
  • 然后执行指令:gcc mainadd.c addfunc.c -o add进行编译

首先了解一下gcc编译器的工作流程:在这里插入图片描述

Linux静态库、动态库(共享库)详解:

  • 在项目开发过程中,经常出现优秀代码重用现象,又或者提供给第三方功能模块却又不想让其看到源代码,这些时候,通常的做法是将代码封装成库或者框架,生成的静态库要和头文件同时发布。
  • 静态库特点: 静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。静态库优点: 寻址方便,速度快;库在链接时被打包到可执行文件中,直接发布可执行程序即可以使用;发布程序无需提供静态库,因为已在app中,移植方便静态库缺点: 静态库的代码被加载到可执行程序中,因此体积过大;如果静态库的函数发生改变,必须重新编译可执行程序;链接时完整的拷贝至可执行文件中,被多次使用就有多份冗余的拷贝;更新、部署、发布、比较麻烦。
  • 动态库特点: 动态库的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,因此代码体积较小,因此在程序运行时还需要动态库存在。动态库优点: 节省内存;易于更新,不用重新编译可执行程序,运行时自动加载;链接时不复制,程序运行时由系统动态加载到内存,供程序使用,系统只加载一次,多个程序可以共用,节省内存。动态库缺点: 延时绑定,速度略慢;发布程序需要提供依赖的动态库。注意: 动态函数库和共享函数库是一个东西(在Linux上叫共享对象库,文件后缀是.so在windows上叫做动态函数加载库,文件后缀是.dll)。
  • Linux中命名系统中共享库的规则:
    在这里插入图片描述

静态库的制作与使用:

  • 命名规则: 静态库文件名的命名方式是“libxxx.a”,库名前加”lib”,后缀用”.a”,“xxx”为静态库名。
  • 制作过程: 原材料:源代码.c 或者 .cpp。
  • 第一步: 将.c文件生成.o,gcc 源代码.c -c这里是要将功能函数的.c文件生成.o文件。就用上面的那个例子:将addfunc.c生成.o文件。
 gcc addfunc.c -c得到:addfunc.o
  • 第二步; 将.o 打包ar rcs 静态库的名字 原材料,原材料就是上面生成的.o文件,静态库名字尽量符合静态库的命名规则。
 ar rcs libaddfunc.a addfunc.o得到:libaddfunc.a
  • 静态库的使用: 当静态库制作完成后,此时不再需要addfunc.c这个文件了,将它移除也不会造成任何影响。但是需要addfunc.h这个文件,因为main函数里面有包含这个头文件。当别人需要你的代码时只需将.h和.a文件提供给他们即可。静态库使用格式:gcc mainadd.c -laddfunc -L ./若直接-l 编译会报错,因为-l 会优先从/urs/lib 或 /urs/local/lib 中去找,但我们想让它优先从当前路径去找,就要用到-L ./。使用静态库时一般去掉lib和后面的.a直接-l+静态库的名字即可。
gcc mainadd.c -laddfunc -L ./ -o add
得到:add这个可执行文件

动态库的生成和使用:

  • 命名规则: 动态库的命名方式与静态库类似,前缀相同,为“lib”,后缀变为“.so”。所以为“libaddfunc.so”
  • 制作指令: gcc -shared -fpic addfunc.c -o libxxx.so 其中 -shared是指定生成动态库,-fpic的作用是:作用于编译阶段,在生成目标文件时就得使用该选项,以生成位置无关的代码。
gcc -shared -fpic addfunc.c -o libaddfunc.so
得到: libaddfunc.so
  • 动态库的使用: 动态库的使用和静态库的使用方法是一样的,gcc mainadd.c -laddfunc -L ./ -o add其中mainadd.c 是主函数,addfunc是动态库的名字。
gcc mainadd.c -laddfunc -L ./ -o add
得到:add这个可执行文件
但是./add会报错,而静态库生成的可执行文件却不会报错,
原因是动态库在生成可执行程序时没有把动态库包含进去,
是在程序运行过程中临时由目标调用动态库,静态库则是已经编译到,目标程序中了。
  • 这时我们就需要将自己制作的动态库拷贝到/user/lib/下面,因为他默认的会从/user/lib/下面去找动态库。
sudo cp libaddfunc.so /usr/lib/
//这时候在执行就不会报错了。
  • 那么如何在程序执行的时候从当前路径下去找动态库呢?通过环境变量LD_LIBRARY_PATH指定动态库搜索路径,export LD_LIBRARY_PATH="/home/pi/linuxfile/file1"但是这样的环境变量是临时的,当退出后还要重新设置环境变量。所以我们可以使用脚本,将export LD_LIBRARY_PATH="/home/pi/linuxfile/file1"放到脚本里面并且添加./add这个可执行文件的名称,然后chmod +x start.sh给这个脚本添加可执行的权限。
    在这里插入图片描述
  • 还可以使用du + 库的名称计算文件或者可执行程序的大小例如:du add或者du libaddfunc.so
  • 除了上面哪种方法以外,还在网上看到以下两种方法:第一种方法:gcc + 源文件 + -L 动态库路径 + -l动态库名 + -I头文件目录 + -o 可执行文件名
    gcc main.c -L lib -l MyTest -I include -o app 然后./app会报错:(执行失败,找不到链接库,没有给动态链接器(ld-linux.so.2)指定好动态库 libmytest.so 的路径)第二种方法:gcc + 源文件 + -I头文件 + libxxx.so + -o 可执行文件名
    gcc main.c -l include lib/libMyTest.so -o app(执行成功,已经指明了动态库的路径)
  • 如何解决第一种方法中找不到链接库的问题?
  • 使用命令ldd app可以查看当前的链接库情况。第一种方法
    export LD_LIBRARY_PATH=自定义动态库的路径(只能起到临时作用,关闭终端后失效)LD_LIBRARY_PATH : 指定查找共享库(动态链接库)时除了默认路径之外的其他路径,该路径在默认路径之前查找。第二种方法:将上述命令写入home目录下的.bashrc文件中,保存后重启终端生效(永久)第三种方法:直接将动态库拷贝到user/lib的系统目录下(强烈不推荐!!)第四种方法:将libmytest.so所在绝对路径追加入到/etc/ld.so.conf文件,使用sudo ldconfig -v 更新
    在这里插入图片描述
    进入/etc/ld.so.conf.d这个文件路径下,新建一个自己的.conf,我这里是mylib.c将动态库的绝对路径加进去然后使用sudo ldconfig -v更新,就可以运行可执行文件了。

Linux环境变量详解:

  • 环境变量的含义: 环境变量一般是指操作系统中指定操作系统运行环境的一些参数。它相当于一个指针,想要查看变量的值,需要加上“$”。
  • 环境变量的分类:作用的范围: 分在Linux中的变量,可以分为环境变量和本地变量:①环境变量:相当于全局变量,存在于所有的Shell中,具有继承性;②本地变量:相当于局部变量只存在当前Shell中,本地变量包含环境变量,非环境变量不具有继承性。 按生存周期分: ①永久:需要修改配置文件,变量永久生效;②暂时:使用export定义,关闭Shell后失效。
  • 环境变量的组织方式: 每个程序都有一张环境表,环境表是一个指针数组,每个指针指向一个以‘\0’结尾的环境字符串。Main函数的第三个参数就是环境表地址。
    在这里插入图片描述
    常见的环境变量:
  • PATH: 变量指定命令的搜索路径。

在这里插入图片描述使用指令echo $PATH:可以查看在当前目录下PATH的值。它表示在当前目录下执行的每一条指令的搜索路径,每个目录以冒号隔开。当执行一条指令时,系统就会从系统文件中去寻找,找到了就执行;否则不执行。

  • HOME: 该变量指定用户的主工作目录,即用户登录到Linux系统时,默认的目录。 这个环境变量一个变量,它的值随着用户的不同而不同。
    普通用户下的主工作目录
    在这里插入图片描述sudo -s进入超级用户权限, 超级用户下的主工作目录

  • LOGNAME: 该变量指定显示用户的登录名。
    在这里插入图片描述

  • HOSTNAME: 该变量指定主机名
    在这里插入图片描述

  • SHELL: 该变量指定用户当前使用的解析器。
    在这里插入图片描述

修改和显示环境变量的命令 :

  • echo: 该命令用于显示某个环境变量的值。

  • env : 该命令指定显示所有的环境变量和值。

  • set: 显示系统中已经存在的shell变量,以及设置shell变量的新变量值。使用set更改shell特性时,符号"+“和”-"的作用分别是打开和关闭指定的模式。set命令不能够定义新的shell变量。如果要定义新的变量,可以使用declare命令以变量名=值的格式进行定义即可。

  • 使用declare命令定义一个新的环境变量"mylove",并且将其值设置为"Visual C++",输入如下命令: declare mylove='Visual C++' #定义新环境变量再使用set命令将新定义的变量输出为环境变量,输入如下命令:set -a mylove #设置为环境变量 执行该命令后,将会新添加对应的环境变量。用户可以使用env命令和grep命令分别显示和搜索环境变量"mylove",输入命令如下:env | grep mylove #显示环境变量值

  • export : 该命令指定设置一个新的环境变量。注意:环境变量一般用英文字母大写加下划线表示。在这里插入图片描述

  • unset : 该命令指定清除环境变量。

在这里插入图片描述

  • readonly : 该命令用于设置只读环境变量,将环境变量MY_ENV设置为只读模式后,就不能在对它进行修改了,直到用户退出登录后才失效。
    5、存放环境变量的文件

几个文件的作用:

  • /etc/profile 该文件的作用是当用户登录时获取系统的环境变量,只获取一次。
  • /etc/bashrc 当执行完/etc/profile文件后,用户想打开bash Shell就会读取该文件。如果想每次打开bash Shell后都执行某些操作,可以在该文件中设置。
  • ~/.bash_profile 每个用户都可使用该文件输入专用于自己使用的shell信息。当用户登录时,该文件仅仅执行一次,默认情况下,它设置一些环境变量,执行用户的.bashrc文件。单个用户此文件的修改只会影响到他以后的每一次登陆系统。因此,可以在这里设置单个用户的特殊的环境变量或者特殊的操作,那么它在每次登陆的时候都会去获取这些新的环境变量或者做某些特殊的操作,但是仅仅在登陆时。
  • ~/.bashrc 该文件包含专用于单个人的bash shell的bash信息,当登录时以及每次打开一个新的shell时,该该文件被读取。单个用户此文件的修改会影响到他以后的每一次登陆系统和每一次新开一个bash。因此,可以在这里设置单个用户的特殊的环境变量或者特殊的操作,那么每次它新登陆系统或者新开一个bash,都会去获取相应的特殊的环境变量和特殊操作。
  • ~/.bash_logout 当每次退出系统(退出bash shell)时,执行该文件。

环境变量部分参考这篇博文

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

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

相关文章

kali扫描内网ip_Metasploit路由转发实现内网渗透

利用背景在渗透的过程中常常会遇到这种场景&#xff1a;我们已经通过web渗透拿下一台内网服务器&#xff0c;为了进一步进行内网渗透&#xff0c;我们会利用“沦陷主机”作为跳板进行进一步的内网渗透&#xff0c;扩大战果。现在假设的场景是此时我们已经拿下一台内网服务器的远…

.NET Core 3.0 中的新变化

译者&#xff1a;楚人Leo译文&#xff1a;http://www.cnblogs.com/leolion/p/10585834.html原文&#xff1a;https://msdn.microsoft.com/en-us/magazine/mt848631.aspx.NET Core 3.0 是 .NET Core 平台的下一主要版本。本文回顾 .NET Core 发展历史&#xff0c;并展示了它是如…

树莓派GPIO口的使用(外设相关开发WringPi库的使用,超声波、继电器)

树莓派的接口&#xff1a; 大而简单的类别&#xff1a;IO口&#xff0c;input和output是相对于主控芯片来说的&#xff0c;是根据MCU和外设之间的关系将IO口的功能分为output和input。当IO作为input使用时外设有&#xff1a;人体传感器、烟雾传感器、火焰传感器、振动传感器等…

volatile指令重排_有多少人面试栽到Volatile上?面试问题都总结到这儿了

Volatile关键字volatile 是Java虚拟机提供的 轻量级 的同步机制.何为 轻量级 呢&#xff0c;这要相对于 synchronized 来说。Volatile有如下三个特点。要搞清楚上面列举的名词 可见性 原子性 指令重排 的含义我们需要首先弄清楚JMM(Java内存模型是怎么回事)JMM规定了内存主要划…

Dubbo核心概念

节点角色规范 节点角色规格Provider提供者公开远程服务Consumer消费者致电远程服务Registry注册表负责服务发现和配置Monitor监视器计算服务调用的数量和耗时Container容器管理服务的生命周期 服务关系 Container负责启动&#xff0c;加载和运行服务Provider。ProviderRegiste…

良心推荐11款可以称得上“神器”的Windows工具集合

1、最快文件搜索工具 Everything&#xff1a;当之无愧的最强本地文件搜索神器&#xff0c;搜索任何关键词基本是秒速出现&#xff0c;比Windows自带的搜索快了太多&#xff0c;电脑文件比较多的人必备&#xff01; 2、专业软件卸载器 Revo Uninstaller Pro&#xff1a;Windows电…

LD3320语音识别模块二次开发及与树莓派间的通讯

实物图如下&#xff1a; 一般这种模块的资料厂家都会给&#xff0c;需要的话可以私信我发邮箱&#xff0c;下面介绍该模块的各种参数。型号&#xff1a;YS-LDV7名称&#xff1a;一体化语音识别模块规格&#xff1a;43*29.7MM供电电压&#xff1a;5V &#xff08;内部工作电压…

多生产者_你是生产者还是消费者?这决定了你的层次。

不知道你有没有注意到&#xff0c;每天乘坐地铁上下班的时候&#xff0c;大部分人都在刷剧、看视频、打游戏等等&#xff0c;总之都属于玩乐。用生产和消费的关系来看的话&#xff0c;其实这一大部分人都属于消费者&#xff0c;“时间和注意力”是他们用于交换的筹码&#xff1…

eclipse Android 开发基础 Activity 窗体 界面

eclipse Android 开发基础 新建工程 新建布局layout,new Android Activity就相当于窗体Form。 新建Activity自动生成src下同名的java代码。 public class Tform2activity extends Activity {Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(saved…

8 种常被忽视的 SQL 错误用法

来源&#xff1a;http://t.cn/R6UMaA11、LIMIT 语句2、隐式转换3、关联更新、删除4、混合排序5、EXISTS语句6、条件下推7、提前缩小范围8、中间结果集下推总结sql语句的执行顺序&#xff1a;FROM <left_table>ON <join_condition><join_type> JOIN <right…

变频器按启动没反应_起重机软启动柜晶闸管损坏维修几大故障

缺相保护功能&#xff1a;工作时&#xff0c;软起动器随时检测三相线电流的变化&#xff0c;一旦发生断流&#xff0c;即可作出缺相保护反应。过热保护功能&#xff1a;通过软起动器内部热继电器检测晶闸管散热器的温度&#xff0c;一旦散热器温度超过允许值后自动关断晶闸管&a…

Redis 的各项功能解决了哪些问题?

作者丨blackheart先看一下Redis是一个什么东西官方简介解释到&#xff1a;Redis是一个基于BSD开源的项目&#xff0c;是一个把结构化的数据放在内存中的一个存储系统&#xff0c;你可以把它作为数据库&#xff0c;缓存和消息中间件来使用。同时支持strings&#xff0c;lists&am…

RocketMQ集成SpringBoot

RocketMQ集成SpringBoot RocketMQ总体架构 RocketMQ基本特性

ASP.NET Core 2.2+Quartz.Net 实现Web定时任务

作者&#xff1a;Julian_酱链接&#xff1a;http://www.cnblogs.com/mi12205599/p/10361763.html作为一枚后端程序狗&#xff0c;项目实践常遇到定时任务的工作&#xff0c;最容易想到的的思路就是利用Windows计划任务/wndows service程序/Crontab程序等主机方法在主机上部署定…

RocketMQ核心概念

生产者Producer和消费者Consumer NameServer作用 Broker和Topic

交叉编译、软硬链接

什么是交叉编译&#xff1f;交叉编译是一个行为&#xff0c;是在一个平台上生成另一个平台上的可执行代码。 本地编译&#xff1a;本地编译可以理解为&#xff0c;在当前编译平台下&#xff0c;编译出来的程序只能放到当前平台下运行。平时我们常见的软件开发&#xff0c;都是…

Linus下安装maven

下载maven安装包 wget http://mirror.bit.edu.cn/apache/maven/binaries/apache-maven-3.2.2-bin.tar.gz 解压 tar -zxvf apache-maven-3.2.2-bin.tar.gz 配置maven环境变量 查看maven解压后安装包目录 vi /etc/profile 进入最底部&#xff0c;按insert,添加环境变量&#x…

linux内核开发基础(linux内核源码、树莓派源码编译、SD卡挂载)

首先下载树莓派linux内核源码&#xff1a; 下载网址&#xff1a;https://github.com/raspberrypi/linux在树莓派使用指令&#xff1a;uname -r查看当前树莓派的版本号&#xff0c;然后选择对应的linux内核版本号进行下载。 将linux内核源码从共享文件夹拷贝到SYSTEM文件夹&am…

Linux实时查看进程命令top笔记

top命令是Linux下常用的性能分析工具&#xff0c;能够实时显示Linux系统中各个进程的资源占用状况&#xff0c;类似于Windows系统的任务管理器功能。 top命令的语法格式&#xff1a; top [-] [d] [p] [q] [c] [C] [S] [s] [n] 常用参数说明 d 指定每两次屏幕信息刷新之间的时间…