【Linux】进程间通信之共享内存(下)

简介: 【Linux】进程间通信之共享内存(下)

下面我们将代码运行起来测试一下:

22666ce1c4b44844b233a167f36444c9.png71f7a0af3448453cafe9f6c890b2e700.png


我们将程序运行起来发现并没有问题,下面我们查看共享内存是否创建成功,ipcs这个命令可以显示出三条资源:

d12f94b447334b4883853acb0c0d9d3c.png

第一条资源为消息队列,第二条资源为共享内存段,第三个为共享内存核心数组,我们主要看第二条,可以看到我们创建的1024大小的共享内存创建成功了。当然我们可以只查第二条,命令是ipcs -m :

0cf9fceb6dd042cdad79fc8173ee3ea7.png

下面我们讲一下上面所代表的意思,key就像文件的inode一样,而shmid就像文件的fd一样shmid才是操作共享内存所需要的核心数据。owner是谁创建的,perms是权限,nattch是与这个共享内存的连接数。下面我们在讲一下删除一个共享内存的命令:ipcrm -m +shmid(刚刚讲过shmid是用来操作共享内存的,与文件的fd作用一样):

fea89b013daf48dc8350c35e91aaa804.png


我们成功的删除了刚刚创建的共享内存。我们接着代码往下写,创建了共享内存后可以让客户端往服务端写一些东西,然后退出的时候需要删除共享内存,我们先来看看如何删除共享内存:


6cf9ba670d6d4976ac90f9f1c2b7382c.png

利用系统调用删除共享内存需要shmctl函数,第一个参数就是共享内存的shmid,第二个参数是指令,也就是说对共享内存做什么操作,我们看看指令有哪些:

54320a79571b40c88b37acade72fcf49.png

常见的指令有这么几个,而IPC_RMID就是真正删除共享内存的操作,第一个IPC_STAT是获取共享内存的属性,而第三个参数是一个共享内存的结构体的指针可以查看共享内存对应的属性:

f3048b36cd304cfcb8a2f462cdb6ac26.png


下面我们就写一个删除共享内存函数:

void delshm(int shmid)
{
    int n = shmctl(shmid,IPC_RMID,nullptr);
    assert(n!=-1);
    (void)n;
}



因为我们删除共享内存的时候不关心它的属性,所以我们直接设为空即可。

a96c0bc32e0645899501cfb28937715a.png

下面我们给大家演示一下查看共享内存的属性:

f881024ce4a54382bcb7e5f03503cab5.pngfecc2836a9974f91a988c559050d39c3.png


下面我们可以在创建共享内存的时候将权限也设置好:

int creatShm(key_t k,int size)
{
    umask(0);
    return createShmHelper(k,size,IPC_CREAT|IPC_EXCL|0666);
}

下面我们要将创建出来的共享内存与进程关联起来,要关联得需要shmat函数:

fcd58f993b9e4031a9292ead4926d2fd.png


第一个参数我们都知道,第二个参数的意思是可以指定将共享内存挂接到指定的地址处(在这里可以设为nullptr,nullptr后操作系统会自己选择合适的地址挂接),第三个参数是设置共享内存是只读的还是什么其他的权限(我们可以设为0,设为0默认是可读可写)

char* attachShm(int shmid)
{
    char* start = (char*)shmat(shmid,nullptr,0);
    return start;
}


4ab9f95c02ed487f979ec36f03d17e95.pngf873ed45566842c4841cc1678166e2de.png


当我们将进程和共享内存关联后,下一步就是退出前将他们去关联,去关联同样也需要函数,这个函数是shmdt:

ce17f85f1cab4b009dfc8ce35f42190e.png

这个函数的参数我们已经讲过了,就是刚刚关联时候给我们返回的那个地址,所以我们可以直接写代码了:

void detachShm(char* start)
{
    int n = shmdt(start);
    assert(n!=-1);
    (void)n;
}


32b0a1a194b249f58cb2c7707c341e48.pngcfe02bf9a9964f2f8e44e18ad3da95d1.png


以上内存的所有点我们就讲完了,下面我们通过一个类封装一下让客户端和服务端的代码可以少一些:

#define SERVER 1
#define CLIENT 0
class Init
{
public:
    Init(int type)
    {
        key_t k = getKey();
        if (type==SERVER)
        {
            shmid = creatShm(k,gsize);
        }
        else 
        {
            shmid = getShm(k,gsize);
        }
        start = attachShm(shmid);
    }
    char* getStart()
    {
        return start;
    }
    ~Init()
    {
        detachShm(start);
        if (type==SERVER)
        {
            delShm(shmid);
        }
    }
private:
    char* start;
    int type;
    int shmid;
}


通过以上类的封装,我们的客户端和服务端就能简化为以下这样:

1d9b3b51f466491cb82d8746542c6b89.pnge4461a60fd354872a4b29cfadd7f35d5.pngf3238f4350fe403bbffafc5615dbb37a.png1b8ab36015514316a6e03014c8a6d6bd.pngf9fb260e1cce4ff08ec0ab54c5b5517c.png

我们可以看到当我们一开始两个端口都运行的时候有两个进程链接在共享内存上,当客户端指令输入完成退出后就只剩下服务端,当服务端也退出后那么连接数就为0了。

以上就是我们共享内存的所有内容,学了共享内存要知道共享内存是进程间通信的几种方式中访问速度最快的。


总结



使用ipcrm -m 命令删除指定共享内存后,是不会直接释放共享内存的,因为共享内存的生命周期是随操作系统的,只有共享内存当前的映射链接数为0才会被删除释放。


使用ipcrm -a 可以删除所有进程间通信资源(a代表all也就是全部的意思)


ipcrm -m删除共享内存,-q删除消息队列,-s删除信号量


共享内存实现实现通信的原理是因为所有进程操作映射同一块物理内存。


共享内存的操作是非进程安全的,多个进程同时对共享内存读写是有可能造成数据的交叉写入或读取,造成数据混乱。


共享内存的删除操作并非是直接删除,而是拒绝后续映射,只有在当前映射链接数为0的时候表示没有进程访问了,才会真正的被删除。


共享内存生命周期随内核,只要不删除,就一直存在于内核中,除非重启系统或者手动删除。

目录
相关文章
|
6天前
|
消息中间件 存储 网络协议
从零开始掌握进程间通信:管道、信号、消息队列、共享内存大揭秘
本文详细介绍了进程间通信(IPC)的六种主要方式:管道、信号、消息队列、共享内存、信号量和套接字。每种方式都有其特点和适用场景,如管道适用于父子进程间的通信,消息队列能传递结构化数据,共享内存提供高速数据交换,信号量用于同步控制,套接字支持跨网络通信。通过对比和分析,帮助读者理解并选择合适的IPC机制,以提高系统性能和可靠性。
59 14
|
10天前
|
缓存 Linux
linux 手动释放内存
在 Linux 系统中,内存管理通常自动处理,但业务繁忙时缓存占用过多可能导致内存不足,影响性能。此时可在业务闲时手动释放内存。
63 17
|
12天前
|
消息中间件 Linux
Linux:进程间通信(共享内存详细讲解以及小项目使用和相关指令、消息队列、信号量)
通过上述讲解和代码示例,您可以理解和实现Linux系统中的进程间通信机制,包括共享内存、消息队列和信号量。这些机制在实际开发中非常重要,能够提高系统的并发处理能力和数据通信效率。希望本文能为您的学习和开发提供实用的指导和帮助。
72 20
|
1月前
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
104 13
|
1月前
|
SQL 运维 监控
南大通用GBase 8a MPP Cluster Linux端SQL进程监控工具
南大通用GBase 8a MPP Cluster Linux端SQL进程监控工具
|
2月前
|
Linux 网络安全 数据安全/隐私保护
Linux 超级强大的十六进制 dump 工具:XXD 命令,我教你应该如何使用!
在 Linux 系统中,xxd 命令是一个强大的十六进制 dump 工具,可以将文件或数据以十六进制和 ASCII 字符形式显示,帮助用户深入了解和分析数据。本文详细介绍了 xxd 命令的基本用法、高级功能及实际应用案例,包括查看文件内容、指定输出格式、写入文件、数据比较、数据提取、数据转换和数据加密解密等。通过掌握这些技巧,用户可以更高效地处理各种数据问题。
214 8
|
2月前
|
监控 Linux
如何检查 Linux 内存使用量是否耗尽?这 5 个命令堪称绝了!
本文介绍了在Linux系统中检查内存使用情况的5个常用命令:`free`、`top`、`vmstat`、`pidstat` 和 `/proc/meminfo` 文件,帮助用户准确监控内存状态,确保系统稳定运行。
855 6
|
2月前
|
Linux
在 Linux 系统中,“cd”命令用于切换当前工作目录
在 Linux 系统中,“cd”命令用于切换当前工作目录。本文详细介绍了“cd”命令的基本用法和常见技巧,包括使用“.”、“..”、“~”、绝对路径和相对路径,以及快速切换到上一次工作目录等。此外,还探讨了高级技巧,如使用通配符、结合其他命令、在脚本中使用,以及实际应用案例,帮助读者提高工作效率。
135 3
|
2月前
|
监控 安全 Linux
在 Linux 系统中,网络管理是重要任务。本文介绍了常用的网络命令及其适用场景
在 Linux 系统中,网络管理是重要任务。本文介绍了常用的网络命令及其适用场景,包括 ping(测试连通性)、traceroute(跟踪路由路径)、netstat(显示网络连接信息)、nmap(网络扫描)、ifconfig 和 ip(网络接口配置)。掌握这些命令有助于高效诊断和解决网络问题,保障网络稳定运行。
109 2
|
1月前
|
Linux Shell
Linux 10 个“who”命令示例
Linux 10 个“who”命令示例
80 14
Linux 10 个“who”命令示例

热门文章

最新文章