当前位置: 首页 > news >正文

使用树莓派学习Linux系统编程的 --- 库编程(面试重点)

在之前的Linux系统编程中,学习了文件的打开;关闭;读写;进程;线程等概念....

本节补充“Linux库概念 & 相关编程”,这是一个面试的重点

分文件编程

在之前的学习中,面对较大的项目比如 STM32的小车 或 香橙派实现的智能垃圾桶 ,都使用了分文件编程的思路。

其 实现的核心思想就是:将功能性函数的实现单独写在其他的地方,在main函数中调用那些封装好的功能性函数。

这样做的好处是:

  • 分模块的编程思想:在实际工作中面对大型项目,可以让A完成串口开发;B完成网络开发,最后只需要他们提供h文件中的函数接口就可以在主函数中直接调用了,测试时发现哪部分有问题可以直接找负责的人,方便调试
  • 代码可移植性更强:因为分文件编程了,串口,网络,语音可能都被封装好了,那么后续如果其他项目需要这些功能就可以直接调用封装好的接口了,最多只需要微调
  • main函数更加精简:由于把功能性函数的实现步骤都封装到其他文件了,main函数就可以专注于项目的整体调用逻辑,使得整个main看起来更加清晰,逻辑通畅

具体步骤

  1. 将功能性函数名和具体实现步骤写在一个.c文件中
  2. 创建一个同名的.h文件,包含所有可能会被调用的函数原型去除函数体
  3. main中包含刚刚创建的.h文件
  4. main中调用被封装好的函数接口
  5. 使用gcc 编译所有相关的.c文件封装函数的.c文件main函数所在的.c文件
  • h文件的大概格式:
int add(int x, int y);
int min(int x, int y);
float div(int x, int y);
  • main函数调用h文件的格式:
#include <stdio.h>
#include "XXX.h" 

Q:为什么同样是调用头文件,有时候使用' <> ',而有时候使用' "" '呢?

A:使用' <> '时,gcc在编译时会去“/usr/include/”或“/usr/local/include/”下找这个头文件;而使用' "" '时,gcc则会优先从代码运行的当前路径去找这个头文件!如果找不到,才会再去“/usr/include/”或“/usr/local/include/”下找这个头文件。

Linux的库

分文件编程的好处已经在刚刚说到,但是实际工作中会出现这种情况:程序员允许别人可以调用他封装好的功能性函数,但是他不希望别人可以看到他具体实现的函数体。在这种情况下,就要引入Linux的库的概念了!

库(程序函数库)是一种可执行的二进制形式、就是将源代码转化为二进制格式,相当于进行了加密,别人可以使用库,但是看不到库中的内容。

库是别人写好的现有的,可以复用的代码,现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。

程序函数库可分为3种类型:静态函数库(static libraries)、共享函数库(shared libraries)、动态加载函数库(dynamically loaded libraries):

  • 静态函数库:在程序执行前就加入到目标程序中的库, 文件后缀是.a 
  • 共享函数库:在程序执行时动态(临时)由目标程序去调用,共享函数库=动态函数库=共享对象库(Linux), 文件后缀是.so 
  • 动态加载函数库:本质上和共享函数库是一个东西,“动态加载数据库”是windows中的叫法,文件后缀是.dll

因此,对于Linux系统来说可以简单的将库分为 动态库 和 静态库

静态库和动态库的比较

静态数据库(libXXX.a
优点
  1. 运行快
  2. 发布程序无需提供静态库,因为已经在app中,移植方便
缺点
  1. 程序大
  2. 更新部署发布麻烦
动态数据库(libXXX.so
优点
  1. 程序小
  2. 升级简单
  3. 不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享(动态)库的实例
缺点
  1. 运行相对慢

  2. 需要提供依赖的动态库

静态库的制作(不太常用了)

制作步骤
  • 使用以下指令将.c文件生成.o文件
gcc a.c b.c -c
  • 使用以下指令将.o文件打包成.a库文件
ar rcs 静态库的名字 原材料
例:ar rcs libXXX.a a.o b.o

这两步完成后,就生成了.a库文件,此时实现功能函数的.c文件和.o文件对于程序运行就不必要了,使得main函数可以调用这个库的条件就是有.h和.a文件,此时代码执行者可以调用库但却无法得知库中函数具体的实现步骤了。

库的使用
gcc XXXXX.c -L 库文件所在目录 -lXXXX -o XXX
//-L:将-L之后跟着的目录作为第一个寻找库文件的目录,寻找的顺序是:-L之后跟着的目录 -->/lib-->/usr/lib-->/usr/local/lib
//-l(小写L):指定库的名字(去掉lib和.a)
//-o:指定生成的最终应用程序的名字

小插曲:gcc编译时“-I(大写i)” 和“-L"的区别:

  • -I(大写i):将-I之后跟着的目录作为第一个寻找头文件的目录,寻找的顺序是:-I之后跟着的目录-->/usr/include-->/usr/local/include
  • -L:将-L之后跟着的目录作为第一个寻找库文件的目录,寻找的顺序是:-L之后跟着的目录 -->/lib-->/usr/lib-->/usr/local/lib
  • 头文件和库文件的关系:库文件可以包含头文件,头文件不可以包含库文件,头文件可视,库文件不可视

由于之前提到过,静态库的优点之一是“发布程序无需提供静态库” ,所以编译完成后,就可以直接运行程序了,不需要任何后缀!

动态库的制作(更常用)

制作步骤
  • 使用以下指令生成动态库:
gcc -shared -fpic xxx.c -o libxxx.so
//-shared用来生成动态库
//-fpic选项作用于编译阶段,在生成目标文件时就得使用该选项,以生成位置无关的代码
库的使用

编译的语句其实和静态库相同:

gcc XXXXX.c -L 库文件所在目录 -lXXXX -o XXX
//-L:将-L之后跟着的目录作为第一个寻找库文件的目录,寻找的顺序是:-L之后跟着的目录 -->/lib-->/usr/lib-->/usr/local/lib
//-l(小写L):指定库的名字(去掉lib和.a)
//-o:指定生成的最终应用程序的名字

注意!虽然编译的语句相同,但是回顾动态库的缺点“需要提供依赖的动态库” ,所以编译完成后不能像使用静态库那样直接运行,这是因为动态库是程序运行中临时调用的,解决办法是将动态库拷贝到/usr/lib/下:

sudo cp libXXXX.so /usr/lib/

然后,再直接运行程序就可以了!

将动态库复制到/usr/lib//lib/下是因为程序执行时动态库的默认搜索路径就是/lib/usr/lib;那么如果可以指定动态库的搜索路径,就可以不需要将库复制了,这就是另一种方法:使用环境变量LD_LIBRARY_PATH指定动态库搜索路径

export LD_LIBRARY_PATH="动态库所在的绝对路径"

通过添加这个环境变量,也可以成功运行程序了,但是这样做有一个问题:这个环境变量是临时的,也就是说只有在当前窗口生效,如果此时通过SSH再连接一个窗口,又会找不到动态库了,解决办法是:写一个脚本start.sh:

export LD_LIBRARY_PATH="动态库所在的绝对路径"./可执行文件

然后给脚本一个可执行的权限:

chmod +x start.sh

其实这个脚本的作用就是在每次执行程序前设置一个临时的环境变量。

动态库的实操演示

首先在树莓派家目录下创建一个mjm_code文件夹,学习用的代码全放在这里面:

然后分别创建一个“test_main.c”和一个“test_func.c”来模拟main函数所在的C文件和封装功能函数的C文件:

test_main.c:

#include <stdio.h>
#include "test_func.h"int main()
{int a;int b;int ret;float ret1;printf("请输入第一个数\n");scanf("%d",&a);printf("请输入第二个数\n");scanf("%d",&b);printf("开始计算\n");ret = add(a,b);printf("相加为%d\n",ret);ret = min(a,b);printf("相减为%d\n",ret);ret = mul(a,b);printf("相乘为%d\n",ret);ret1 = div(a,b);printf("相除为%f\n",ret1);return 0;
}

test_func.c:

int add(int a,int b)
{return a+b;
}
int min(int a,int b)
{return a-b;
}
int mul(int a,int b)
{return a*b;
}
float div(int a,int b)
{return (float)a/b;
}

test_func.h:

int add(int a,int b);
int min(int a,int b);
int mul(int a,int b);
float div(int a,int b);

然后尝试编译运行:

 

没有报错,程序正常运行,到此为止就是一个分文件编程的典型例子。

接下来,尝试将test_func.c做成一个动态库:(库名我这里叫“scalc”)

 gcc -shared -fpic test_func.c -o libscalc.so

 

 然后进行编译:(我生成了一个叫“calc”的可执行程序)

gcc test_main.c -L . -lscalc -o calc
//-L后的“.”代表当前路径

然后将生成的.so文件复制到usr/lib/下,并删除当前路径下的.so文件:

1. sudo cp libscalc.so /usr/lib/
2. rm libscalc.so //可以不删,删了是为了证明复制到/usr/lib下之后当前路径的.so就没啥用了

 最后尝试运行:

成功运行!此时程序的执行只依赖.h文件和.so文件了,执行者可以调用接口但并不能查看test_func.c中功能函数的具体实现,因为这个.c文件已经被制作成.so的库了。 ​​​​​​​

相关文章:

使用树莓派学习Linux系统编程的 --- 库编程(面试重点)

在之前的Linux系统编程中&#xff0c;学习了文件的打开&#xff1b;关闭&#xff1b;读写&#xff1b;进程&#xff1b;线程等概念.... 本节补充“Linux库概念 & 相关编程”&#xff0c;这是一个面试的重点&#xff01; 分文件编程 在之前的学习中&#xff0c;面对较大的…...

vs2017打开工程提示若要解决此问题,请使用以下选择启动 Visual Studio 安装程序: 用于 x86 和 x64 的 Visual C++ MFC

下载安装文件。 下载之后点击C项目&#xff0c;他会提示需要安装编译依赖。这个时候需要选择 用于 x86 和 x64 的 Visual C MFCWindows SDK 版本8.1 点击右下角的安装等待即可 error MSB8036: 找不到 Windows SDK 版本8.1。请安装所需的版本的 Windows SDK 或者在项目属性页…...

Redis学习笔记17:基于spring data redis及lua脚本批处理scan指令查询永久有效的key

Redis的KEYS和SCAN指令都可以用于在数据库中搜索匹配指定模式的键。然而&#xff0c;它们之间有一些关键的区别&#xff1b; KEYS指令会在整个数据库中阻塞地执行匹配操作&#xff0c;并返回匹配的键列表。如果数据库很大&#xff0c;或者匹配的键很多&#xff0c;将会对性能产…...

今天遇到Windows 10里安装的Ubuntu(WSL)的缺点

随着技术的发展&#xff0c;越来越多开发者转向使用 Windows Subsystem for Linux&#xff08;WSL&#xff09;在 Windows 10 上进行开发&#xff0c;也就是说不用虚拟机&#xff0c;不用准备多一台电脑&#xff0c;只需要在Windows 10/11 里安装 WSL 就能体验 Linux 系统。因此…...

hive sql多表练习

hive sql多表练习 准备原始数据集 学生表 student.csv 讲师表 teacher.csv 课程表 course.csv 分数表 score.csv 学生表 student.csv 001,彭于晏,1995-05-16,男 002,胡歌,1994-03-20,男 003,周杰伦,1995-04-30,男 004,刘德华,1998-08-28,男 005,唐国强,1993-09-10,男 006,陈道…...

论文速览 Arxiv 2023 | DMV3D: 单阶段3D生成方法

注1:本文系“最新论文速览”系列之一,致力于简洁清晰地介绍、解读最新的顶会/顶刊论文 论文速览 Arxiv 2023 | DMV3D: DENOISING MULTI-VIEW DIFFUSION USING 3D LARGE RECONSTRUCTION MODEL 使用3D大重建模型来去噪多视图扩散 论文原文:https://arxiv.org/pdf/2311.09217.pdf…...

访问限制符说明面向对象的封装性

1 问题 Java中4种“访问控制符”分别为private、default、protected、public&#xff0c;它们说明了面向对象的封装性&#xff0c;所以我们要利用它们尽可能的让访问权限降到最低&#xff0c;从而提高安全性。 private表示私有&#xff0c;只有自己类能访问&#xff0c;属性可以…...

python趣味编程-5分钟实现一个贪吃蛇游戏(含源码、步骤讲解)

Python 贪吃蛇游戏代码是用 Python 语言编写的。在这个贪吃蛇游戏中,Python 代码是增强您在创建和设计如何使用 Python 创建贪吃蛇游戏方面的技能和才能的方法。 Python Tkinter中的贪吃蛇游戏是一个简单干净的 GUI,可轻松玩游戏。游戏设计非常简单,用户不会觉得使用和理解…...

如何在虚拟机的Ubuntu22.04中设置静态IP地址

为了让Linux系统的IP地址在重新启动电脑之后IP地址不进行变更&#xff0c;所以将其IP地址设置为静态IP地址。 查看虚拟机中虚拟网络编辑器获取当前的子网IP端 修改文件/etc/netplan/00-installer-config.yaml文件&#xff0c;打开你会看到以下内容 # This is the network conf…...

代码随想录算法训练营第二十九天| 491 递增子序列 46 全排列

目录 491 递增子序列 46 全排列 491 递增子序列 在dfs中进行判断&#xff0c;如果path的长度大于1&#xff0c;则将其添加到res中。 本题nums中的元素的值处于-100与100之间&#xff0c;可以将元素映射0到199之间并且通过布尔数组st来记录此层中元素是否被使用过&#xff0c;…...

(动手学习深度学习)第13章 实战kaggle竞赛:CIFAR-10

导入相关库 import collections import math import os import shutil import pandas as pd import torch import torchvision from torch import nn from d2l import torch as d2l下载数据集 d2l.DATA_HUB[cifar10_tiny] (d2l.DATA_URL kaggle_cifar10_tiny.zip,2068874e4…...

Go 语言中的map和内存泄漏

map在内存中总是会增长&#xff1b;它不会收缩。因此&#xff0c;如果map导致了一些内存问题&#xff0c;你可以尝试不同的选项&#xff0c;比如强制 Go 重新创建map或使用指针。 在 Go 中使用map时&#xff0c;我们需要了解map增长和收缩的一些重要特性。让我们深入探讨这一点…...

前缀和(c++,超详细,含二维)

前缀和与差分 当给定一段整数序列a1,a2,a3,a4,a5…an; 每次让我们求一段区间的和&#xff0c;正常做法是for循环遍历区间起始点到结束点&#xff0c;进行求和计算&#xff0c;但是当询问次数很多并且区间很长的时候 比如&#xff0c;10^5 个询问和10^6区间长度&#xff0c;相…...

详解FreeRTOS:二值信号量和计数信号量(高级篇—2)

目录 1、二值信号量 1.1、二值信号量运行机制 1.2、创建二值信号量 1...

持续集成交付CICD:Jenkins通过API触发流水线

目录 一、理论 1.HTTP请求 2.调用接口的方法 3.HTTP常见错误码 二、实验 1.Jenkins通过API触发流水线 三、问题 1.如何拿到上一次jenkinsfile文件进行自动触发流水线 一、理论 1.HTTP请求 &#xff08;1&#xff09;概念 HTTP超文本传输协议&#xff0c;是确保服务器…...

【Python】12 GPflow安装

概述 GPflow 是一个基于TensorFlow 在 Python 中构建高斯过程模型的包。高斯过程是一种监督学习模型。 高斯过程的一些优点是&#xff1a; 不确定性是高斯过程的固有部分。高斯过程可以在不知道答案时告诉您。适用于小型数据集。如果您的数据有限&#xff0c;高斯过程可以从…...

Ubuntu源码编译gdal3.6.2

在华为云申请了一台Ubuntu v18的机器,乱七八糟的不要装。 apt install build-essential pkg-config -y cmake-3.21.1 apt-get install openssl libssl-dev 过程参考&#xff1a;Yukon for PostgreSQL_格來羙、日出的博客-CSDN博客 zlib-1.2.9(不需要) 如果用系统的后面gd…...

【LeetCode】160. 相交链表

160. 相交链表 难度&#xff1a;简单 题目 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 图示两个链表在节点 c1 开始相交&#xff1a; 题目数据 保证 整个链式结构中…...

数据集笔记:NGSIM (next generation simulation)

1 数据集介绍 数据介绍s Next Generation Simulation (NGSIM) Open Data (transportation.gov) 数据地址&#xff1a;Next Generation Simulation (NGSIM) Vehicle Trajectories and Supporting Data | Department of Transportation - Data Portal 时间2005年到2006年间地…...

解决docker运行elastic服务端启动不成功

现象&#xff1a; 然后查看docker日志&#xff0c;发现有vm.max_map_count报错 ERROR: [1] bootstrap checks failed [1]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144] 解决办法&#xff1a; 1. 宿主机&#xff08;运行doc…...

mysql数据库中mysql database 数据被破坏产生的一系列问题

在执行sql脚本时&#xff0c;没有注意到sql脚本文件包含了对mysql 原始数据库的操作&#xff0c;执行了脚本。 脚本执行成功之后&#xff0c;登录或链接数据库查看数据时报错&#xff1a; The user specified as a definer (‘mysql.infoschema’‘localhost’) does not exis…...

基于变形卷积和注意机制的带钢表面缺陷快速检测网络DCAM-Net(论文阅读笔记)

原论文链接->DCAM-Net: A Rapid Detection Network for Strip Steel Surface Defects Based on Deformable Convolution and Attention Mechanism | IEEE Journals & Magazine | IEEE Xplore DCAM-Net: A Rapid Detection Network for Strip Steel Surface Defects Base…...

05-Spring Boot工程中简化开发的方式Lombok和dev-tools

简化开发的方式Lombok和dev-tools Lombok常用注解 Lombok用标签方式代替构造器、getter/setter、toString()等重复代码, 在程序编译的时候自动生成这些代码 注解名功能NoArgsConstructor生成无参构造方法AllArgsConstructor生产含所有属性的有参构造方法,如果不希望含所有属…...

AIGC 技术在淘淘秀场景的探索与实践

本文介绍了AIGC相关领域的爆发式增长&#xff0c;并探讨了淘宝秀秀(AI买家秀)的设计思路和技术方案。文章涵盖了图像生成、仿真形象生成和换背景方案&#xff0c;以及模型流程串联等关键技术。 文章还介绍了淘淘秀的使用流程和遇到的问题及处理方法。最后&#xff0c;文章展望…...

ANSYS网格无关性检查

网格精度对应力结果存在很大的影响&#xff0c;有时候可以发现&#xff0c;随着网格精度逐渐提高&#xff0c;所求得的最大应力值逐渐趋于收敛。 默认网格&#xff1a; 从默认网格下计算出的应力云图可以发现&#xff0c;出现了的三处应力奇异点&#xff0c;此时算出的应力值是…...

设计模式-责任链-笔记

动机&#xff08;Motivation&#xff09; 在软件构建过程中&#xff0c;一个请求可能被多个对象处理&#xff0c;但是每个请求在运行时只能有个接受者&#xff0c;如果显示指定&#xff0c;将必不可少地带来请求者与接受者的紧耦合。 如何使请求的发送者不需要指定具体的接受…...

SpringMvc请求原理流程

springmvc是用户和服务沟通的桥梁&#xff0c;官网提供了springmvc的全面使用和解释&#xff1a;DispatcherServlet :: Spring Framework 流程 1.Tomcat启动 2.解析web.xml文件&#xff0c;根据servlet-class找到DispatcherServlet&#xff0c;根据init-param来获取spring的…...

【开源】基于Vue.js的音乐偏好度推荐系统的设计和实现

项目编号&#xff1a; S 012 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S012&#xff0c;文末获取源码。} 项目编号&#xff1a;S012&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、系统设计2.1 功能模块设计2.1.1 音乐档案模块2.1…...

采集1688整店商品(店铺所有商品、店铺列表api)

返回数据&#xff1a; 请求链接 {"user": [],"items": {"item": [{"num_iid": "738354436678","title": "国产正品i13 promax全网通5G安卓智能手机源头厂家批发手机","pic_url": "http…...

IObit Unlocker丨解除占用程序软件

更多内容请收藏&#xff1a;https://rwx.tza-3.xyz 官网&#xff1a;IObit Unlocker “永远不用担心电脑上无法删除的文件。” 界面简单&#xff0c;支持简体中文&#xff0c;一看就会&#xff0c;只需要把无法删除/移动的文件或整个U盘拖到框里就行。 解锁率很高&#xff0c;…...