学习系统编程No.16【进程间通信】

简介: 学习系统编程No.16【进程间通信】

引言:

北京时间:2023/4/9/20:44,昨天,也就是这个周末的星期六,就是传说中的蓝桥杯,哈哈哈!摆烂,做题方面真不怎么行,可惜,当初可能是年少轻狂或者说是没什么经验阅历,希望在有了这次的经历之后,明年的今天,能够更加从容吧!谁让我们平时不怎么做题呢?准确的来说是没什么做题的习惯,也可以说是没什么时间做题,虽然我从小就知道时间像海绵里的水,挤一挤总是有的,但一个懒字了的,例如,蓝桥杯回来,本可以直接开始写博客,但是直接摆烂到了现在,算了,主要是没什么太大的压力(这个可能就是当代大一学生的现状,没目标,没压力),这种情况下,一个人有100中说服自己的理由摆烂,我也不例外,哈哈哈!但,还是那句话,摆烂归摆烂,不放弃就行,有小目标就好,哈哈哈!当然,像我其实压力还是很大的,最直接的一点就是CSDN上各路大佬坚持更新,我们自然而然也不甘屈居人后啦!所以导致我还是比较容易上道!所以今天我们就来学习一下有关进程间通信的知识和上篇博客有关动静态库的知识吧!


回顾动静态库

上篇博客我们了解到了,动态库由于使用的时候,不是把库中的所有数据拷贝到目标程序中,而是通过头文件的形式被调用,所以只有编译器可以识别到动态库路径,而操作系统不能识别,这样就会导致动态库在使用时,也就是可执行程序要被执行时,操作系统出现链接错误,并且了解到,为了解决这个问题,有三种解决方式,如下:


1.将库路径导入到环境变量中(临时)

2.软连接(永久)

3.配置文件方案


并且上篇博客,我们已经了解了前面两种,导入环境变量和建立软链接,所以接下来就让我们学习一下第三种,配置文件方案的方式吧!并且复习一下前两种,导入环境变量和创建软链接:


导入环境变量

也就是将动态库所在的路径导入到操作系统可以默认识别到的环境变量之中,因为本质就是为了让动态库所处的路径可以被操作系统找到,此时这个环境变量为:&LD_LIBRARY_PATH,所以此时想要让操作系统找到动态库路径,只要把动态库路径导入到这个环境变量中,就行,指令:export LD_LIBRARY_PATH=&LD_LIBRARY_PATH:"动态库所在的路径",所以当我们把动态库所处的路径导入到了这个环境变量中之后,操作系统此时就可以找到对应的路径了,如下图所示:


image.png


建立软链接

还是明白,本质上就是为了让操作系统可以找到动态库所处路径,所以建立软链接的本质就是给动态库所处的路径建立一个在操作系统默认可以识别到的路径下的映射文件,指令:sudo ln -s /home/vimtest/其他人的动静态库/我的动态库/lib/libmymath.so /lib64/libmymath.so,如下图:


image.png

表示的就是,把动态库所处的路径在操作系统默认可以识别的lib64路径下建一个libmymath.so的软链接映射文件

如下图:此时操作系统默认就可以找到动态库所处的路径了

image.png


配置文件方案

首先还是明白,不管是那种方式,它的本质都是为了可以让操作系统找到动态库所在的文件路径,所以配置文件的方式,同理,如下图所示,并且注意:在Linux系统下,默认存在一个配置文件路径


image.png


并且明白,我们是可以在该配置文件路径下,创建自己的文件,指令:sudo touch /etc/ld.so.conf.d/bit_107.conf

image.png

如上图,我们就可以发现,在系统的配置文件路径下,此时就有了bit_107.conf这个文件,所以此时我们只需要把动态库所在的路径写入该文件中,如下图:

image.png

并且最后将这个配置文件的路径重新激活,指令:sudo ldconfig,此时就可以让动态库所在的路径被操作系统识别到了,如下图所示:

image.png

总:通过上述三种方式,此时就可以明白,操作系统在执行一个可执行程序的时候,有三种方式去寻找相应的动态库路径



深入动静态库内部

首先明白,上述的知识和上篇博客的知识,本质上只是动静态库在操作方面的知识,所以此时就让我们深入动静态库的内部,具体的看一看动静态库吧!(理论)


本质上还是动静态库在使用特征上的不同:使用静态库时,目标程序需要把整个静态库的实现给拷贝到程序中,而动态库则是通过头文件中函数接口的声明,间接使用动态库中函数接口的实现,并且动态库是可以通过条件判断来区分被使用了的函数接口和没被使用的函数接口,达到精准使用的能力,不需要盲目拷贝


当明白了上述知识,此时轻而易举就可以知道 ,当静态库加载到了程序之中,那么此时就会非常的占用资源,无论时空间资源,还是网络资源,而动态库在使用的时候,由于只是将头文件加载到了目标程序,而整个动态库的实现是在程序被执行的时候才加载到内存之中(因为本质上是二进制文件而已),所以此时动态库的使用将不会那么的占用资源,如下图所示:


静态库


image.png


动态库

动态库链接到目标程序,此时并没有拷贝动态库中的具体内容,而只是将动态库所对应的接口实现的地址通过头文件和条件判断替换到相应目标程序所对应的外部符号而已,具体过程如下图所示:


image.png


总的来说,就是在使用动态库的时候,不仅需要将目标程序加载到内存,还需要将动态库也加载到内存

6TFDD

并且还要 注意 ,根据上图,我们可以知道,物理内存中已经存放着相应的动态库了,如果此时别的程序,也就是别的进程,也同样需要用到该动态库,那么此时就当操作系统识别到内存中已经有相应的库,此时就不需要重新从磁盘中加载,而是直接将动态库通过页表映射到自己地址空间的共享区中就行,达到一库多用的作用,这样就可以大大的节省资源,无论是操作系统效率方面还是时空方面


如何理解动态库地址(fPIC

搞定了上述有关,动静态库在内存中的是如何调用的之后,此时我们就再深入了解一下动静态库具体的寻址方式,目的就是为了理解fPIC(与位置无关码)的相关知识,如下述所说:


首先第一点要明白,一个程序是允许同时存在多个地址的,就类比为,一个人是允许有多个名字或者多个编号,学号、宿舍号、身份证号,明白了这点之后,显然就可以知道,一个程序肯定是存在不同的地址的,例,磁盘中的逻辑地址或者物理内存中的物理地址或者是虚拟地址空间中的虚拟地址,也就是表明,一个客观存在的物体或者人,在不同的场景之下,就会存在不同的属性,这个属性可能是形态上的,也可能是逻辑上的,明白了这点,就让我们继续深入地址吧!


明白了上述的知识,知道一个程序可以有不同的地址,逻辑地址,物理地址,虚拟地址,并且明白,这些不同的地址之所有有不同的名字,只是因为程序所处的场景不同而已,所以总的来说程序有很多地址,并且这写地址会因为场景不同而不同,但是总的来说,地址本质上只有两类,一类是绝对地址(静态库),一类是相对地址(动态库),并且明白虚拟地址空间中的编址属于绝对地址


理解绝对地址和相对地址:

相信我们以前都了解过什么是绝对路径,什么是相对路径,同理,在编址的时候,地址也是一样的,绝对地址就是像物理内存中的物理地址一样,内存中的每一个字节都有属于自己的编号(地址),这个就叫绝对地址,而相对地址,就像是磁盘中的逻辑地址一样,以一个固定的点或者值为参照,然后通过偏移量的形式来进行编址,这个就是相对地址


为什么动态库使用相对编址:

无论是从上篇博客知识,还是上述知识,此时我们都明白,一个目标程序在链接静态库的时候,是直接将静态库中所有的接口实现给拷贝到目标程序中,所以此时进程虚拟地址空间通过页表映射物理内存的时候,虚拟地址空间上存放的就是通过页表映射的物理内存上目标程序完整代码,使用绝对地址存放毫无关系,只要操作系统能找到就行;而动态库由于不同的进程,运行程度不同或者是运行的程序不同,需要使用的动态库接口数量上或者接口实现上不同,或者是需要使用的第三方库不同,所以注定每一个目标程序的虚拟地址空间上存储的动态库不同,每一个进程的地址空间不同,每一个进程的共享区间上存储的接口实现代码不同,所以动态库不允许使用绝对地址,而要使用相对地址,具体理由如下:


动态库不能使用绝对编址是因为动态库在被加载时,会被映射到进程的地址空间中,并且动态库是被多个程序共享的,而每个程序的内存地址空间都是不同的,所以动态库不能使用绝对编址是因为动态库是在被加载到进程的内存空间中时确定其最终的内存位置的,而不同进程的内存地址空间不同(可执行程序不同),因此,如果动态库使用绝对地址进行编址,那么在加载该库的不同进程中,其代码和数据可能会被映射到不同的内存地址上。这会导致代码无法在多个进程之间共享,因为其中一个进程中的地址无法被其他进程正确解释。因此,动态库必须采用相对地址,以确保其代码和数据可以在所有进程中使用相同的偏移量进行访问


如下图所示:


image.png



如上图,就是为什么要使用相对路径,而不是绝对路径,并且注意:动态库中的所有函数接口实现的地址都是偏移量,并且默认从0开始并

究极理解:

所以本质上动态库不允许使用绝对地址,就是因为地址空间和内存地址的映射关系是对应的,而地址空间上的动态库由于程序代码的不同,导致动态库不同,但又因为进程之间是共用一份动态库,所以导致地址空间上动态库的接口也必须相同,否则就不能通过对应的映射关系找到内存上的那份唯一的动态库数据,所以此时地址空间上就不能使用绝对地址,从而使用相对地址,因为使用相对地址,此时就可以通过动态库的起始位置加偏移量(只要各个进程使用的接口实现是相同的,偏移量就相同),所以调用时,调用的动态库的接口就相同,最后再根据映射关系,访问到的内存上的动态库的接口实现就相同


所以得出结论:


总:这就是为什么要使用fPIC的原因


反正终极目的就是理解动态库如何实现局部加载,相对地址的概念


测试动静态库的具体使用场景

明白了上述的知识,此时动静态库有关操作和理论方面的知识我们就搞定了,此时我们就再深入几个场景看看,动静态库具体还有什么特点,首先要明白,一个庞大的程序,是拥有非常多的代码和数据的,此时就不仅需要有动态库的实现,此时还要有静态库的实现,所以大部分的程序都是静态库和动态库同时使用来完成的,但是一般一些小的程序 ,仅仅使用动态库或者静态库就能完成,所以假如此时有一个动态库和一个静态库,并且这两个库中的函数接口实现都是目标程序需要的,那么此时系统是链接静态库还是链接动态库呢?如下图所示:


image.png


所以此时我们知道,当一个库中同时有静态库和动态库时,此时程序优先调用的是动态库,那么我相信,大家此时肯定有一个疑问,那就是那么如何优先调用静态库呢?如下图所示:

image.png


所以我们就知道了,当一个库中同时拥有动态库和静态库时,虽然默认的是动态库,但是我们依然可以优先调用静态库,如下图通过查看文件的属性,此时我们也可以看出程序链接的是动态库,还是静态库,具体指令:

gcc -o mytest-d main.c -I include -L lib -l mymath

gcc -o mytest-s main.c -I include -L lib -l mymath -static


image.png


总的来说就是有什么用什么,但是默认动态库优先,没有动态库才链接静态库

进程间通信


image.png

进程间通信发展

1.管道 2.System V进程间通信 3.POSIX进程间通信

进程间通信分类

1.管道 2.匿名管道pipe 3.命名管道


详细知识下篇博客见



总结:动静态库的知识真的非常多,终于全部搞定了,难搞呀!接下来,就让我们再谈进程吧!进程间通行详解,下篇博客见啦!

相关文章
|
1月前
|
安全 Python
告别低效编程!Python线程与进程并发技术详解,让你的代码飞起来!
【7月更文挑战第9天】Python并发编程提升效率:**理解并发与并行,线程借助`threading`模块处理IO密集型任务,受限于GIL;进程用`multiprocessing`实现并行,绕过GIL限制。示例展示线程和进程创建及同步。选择合适模型,注意线程安全,利用多核,优化性能,实现高效并发编程。
39 3
|
28天前
|
运维 关系型数据库 MySQL
掌握taskset:优化你的Linux进程,提升系统性能
在多核处理器成为现代计算标准的今天,运维人员和性能调优人员面临着如何有效利用这些处理能力的挑战。优化进程运行的位置不仅可以提高性能,还能更好地管理和分配系统资源。 其中,taskset命令是一个强大的工具,它允许管理员将进程绑定到特定的CPU核心,减少上下文切换的开销,从而提升整体效率。
掌握taskset:优化你的Linux进程,提升系统性能
|
23天前
|
弹性计算 Linux 区块链
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
30 4
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
|
8天前
|
Python
python Process 多进程编程
python Process 多进程编程
19 1
|
17天前
|
安全 开发者 Python
跨越编程孤岛,构建互联大陆:深入探索Python进程间通信的奥秘,解锁高效协作新纪元!
【8月更文挑战第3天】在编程领域,Python 因其简洁强大而广受欢迎。但随着项目规模扩大,单进程难以应对复杂需求,此时多进程间的协同就显得尤为重要。各进程像孤岛般独立运行,虽提升了稳定性和并发能力,但也带来了沟通障碍。为解决这一问题,Python 提供了多种进程间通信(IPC)方式,如管道、队列和套接字等,它们能有效促进数据交换和任务协作,使各进程像大陆般紧密相连。通过这些机制,我们能轻松搭建起高效的多进程应用系统,实现更加复杂的业务逻辑。
18 2
|
19天前
|
安全 开发者 Python
揭秘Python IPC:进程间的秘密对话,让你的系统编程更上一层楼
【8月更文挑战第1天】在系统编程中, 进程间通信 (IPC) 是连接独立进程的关键技术, 提升了系统的并发性和灵活性。Python 提供了丰富的 IPC 机制, 包括管道 (`Pipe`), 队列 (`Queue`), 共享内存 (`Value`, `Array`) 和套接字 (`Sockets`)。这些机制支持不同的应用场景, 如简单的父子进程通信或复杂的分布式系统构建。合理选择 IPC 方法可帮助开发者构建高效、可靠的多进程应用, 但同时也需注意同步和数据一致性等问题。
30 1
|
26天前
|
算法 调度 UED
操作系统中的进程调度策略及其对系统性能的影响
本文深入探讨了操作系统中进程调度的多种策略,包括先来先服务、短作业优先、优先级调度、轮转与多级队列等,并分析了它们对系统性能的具体影响。通过比较不同调度算法的效率和公平性,本文旨在为系统管理员提供选择合适调度策略的依据,以优化系统的整体表现。
|
8天前
|
并行计算 开发者 Python
解锁Python多进程编程的超能力:并行计算的魔法与奇迹,探索处理器核心的秘密,让程序性能飞跃!
【8月更文挑战第12天】在Python编程领域,多进程编程是一项关键技能,能有效提升程序效率。本文通过理论与实践结合,深入浅出地介绍了Python中的多进程编程。首先解释了多进程的概念:即操作系统中能够并发执行的多个独立单元,进而提高整体性能。接着重点介绍了`multiprocessing`模块,演示了如何创建和启动进程,以及进程间的通信方式,如队列等。此外,还提到了更高级的功能,例如进程池管理和同步原语等。通过这些实例,读者能更好地理解如何在实际项目中利用多核处理器的优势,同时注意进程间通信和同步等问题,确保程序稳定高效运行。
21 0
|
1月前
|
小程序 Linux
【编程小实验】利用Linux fork()与文件I/O:父进程与子进程协同实现高效cp命令(前半文件与后半文件并行复制)
这个小程序是在文件IO的基础上去结合父子进程的一个使用,利用父子进程相互独立的特点实现对数据不同的操作
|
2月前
|
监控 Linux 应用服务中间件
探索Linux中的`ps`命令:进程监控与分析的利器
探索Linux中的`ps`命令:进程监控与分析的利器