Linux进程通信——共享内存(中)

简介: Linux进程通信——共享内存(中)

shmat

第一个参数是想和哪一个共享内存关联,第二个参数是想把这个共享内存映射到地址空间的哪个地方(不常用),第三个权限是读写权限(一般设置为0)。

返回值是将映射到虚拟地址空间的起始地址位置返回。(等价于C语言的malloc)

失败返回-1。

void* attachshm(int shmid)
{
    void* p = shmat(shmid, nullptr, 0);
    if((long long)p == -1L)//因为linux系统是64位,一个地址是8个字节,所以要变成8个字节大小的数据类型做对比
    {
        std::cerr << errno << ":" << strerror(errno) << std::endl;
        exit(4);
    }
    return p;
}

这里就代表挂接成功了,这个共享内存挂接了一个进程。

那么如何去关联呢?

shmdt

其实就是调用去卸载当前进程共享内存的地虚拟地址空间,参数就是shmat的返回值。

返回值成功是0,错误是-1.

void detachshm(void* p)
{
    if(shmdt(p) == -1)
    {
        std::cerr << errno << ":" << strerror(errno) << std::endl;
    }
}

然后完善一下另一个文件中的代码:

这一份不需要他释放掉共享内存。

这里让server多休息一会。

通信

然后来完善通信的一下代码:

#ifndef _COMM_HPP_
#define _COMM_HPP_
#include<iostream>
#include<cassert>
#include<cstring>
#include<cerrno>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<cstdlib>
#include<unistd.h>
#define PATHNAME "."//ftok的第一个参数,是一个合法路径
#define PROJ_IO 0X666//ftok的第二个参数
#define MAX_SIZE 4096//共享内存的大小
key_t getkey()
{
    key_t k = ftok(PATHNAME, PROJ_IO);
    if(k < 0)
    {
        std::cerr << errno << ":" << strerror(errno) << std::endl;
        exit(1);
    }
    return k;
}
int getshmhelper(key_t k, int flags)
{
    int shmid = shmget(k, MAX_SIZE, flags);
    if(shmid < 0)
    {
        std::cerr << errno << ":" << strerror(errno) << std::endl;
        exit(2);
    }
    return shmid;
}
int getshm(key_t k)//获取共享内存
{
    return getshmhelper(k, IPC_CREAT);//没有就创建,有就获取
}
int createshm(key_t k)//创建共享内存
{
    return getshmhelper(k, IPC_CREAT | IPC_EXCL | 0600);//没有创建,有就报错,这里创建内存需要给对应的权限
}
void delshm(int shmid)
{
    if(shmctl(shmid, IPC_RMID, nullptr) == -1)
    {
        std::cerr << errno << ":" << strerror(shmid) << std::endl;
        exit(3);
    }
}
void* attachshm(int shmid)
{
    void* p = shmat(shmid, nullptr, 0);
    if((long long)p == -1L)//因为linux系统是64位,一个地址是8个字节,所以要变成8个字节大小的数据类型做对比
    {
        std::cerr << errno << ":" << strerror(errno) << std::endl;
        exit(4);
    }
    return p;
}
void detachshm(void* p)
{
    if(shmdt(p) == -1)
    {
        std::cerr << errno << ":" << strerror(errno) << std::endl;
    }
}
#endif
#include"shm.hpp"
int main()
{
    key_t k = getkey();
    printf("0x%x\n",k);
    int shmid = getshm(k);//接收共享内存
    printf("shmid : %d\n", shmid);
    char* p = (char*)attachshm(shmid);//关联
    printf("attach sucess, address p: %p\n",p);
    //使用
    const char* str = "hello server, 我是另一个进程,我在和你通信";
    pid_t id = getpid();
    int count = 0;
    while(true)
    {
        sleep(1);
        snprintf(p, MAX_SIZE, "%S[pid:%d][消息编号:%d]", str, id, count++);
    }
    detachshm(p);//去关联
    return 0;
}
#include"shm.hpp"
int main()
{
    key_t k = getkey();
    printf("0x%x\n",k);
    int shmid = createshm(k);//创建共享内存
    printf("shmid : %d\n", shmid);
    char* p = (char*)attachshm(shmid);//关联
    printf("attach sucess, address p: %p\n",p);
    //使用
    while(true)
    {
        printf("client say: %s\n",p);
        sleep(1);
    }
    detachshm(p);//去关联
    sleep(10);
    delshm(shmid);//删除共享内存
    return 0;
}

相关文章
|
1月前
|
消息中间件 存储 网络协议
从零开始掌握进程间通信:管道、信号、消息队列、共享内存大揭秘
本文详细介绍了进程间通信(IPC)的六种主要方式:管道、信号、消息队列、共享内存、信号量和套接字。每种方式都有其特点和适用场景,如管道适用于父子进程间的通信,消息队列能传递结构化数据,共享内存提供高速数据交换,信号量用于同步控制,套接字支持跨网络通信。通过对比和分析,帮助读者理解并选择合适的IPC机制,以提高系统性能和可靠性。
138 14
|
1月前
|
缓存 Linux
linux 手动释放内存
在 Linux 系统中,内存管理通常自动处理,但业务繁忙时缓存占用过多可能导致内存不足,影响性能。此时可在业务闲时手动释放内存。
112 17
|
12天前
|
消息中间件 Linux
Linux中的System V通信标准--共享内存、消息队列以及信号量
希望本文能帮助您更好地理解和应用System V IPC机制,构建高效的Linux应用程序。
81 48
|
5天前
|
存储 网络协议 Linux
【Linux】进程IO|系统调用|open|write|文件描述符fd|封装|理解一切皆文件
本文详细介绍了Linux中的进程IO与系统调用,包括 `open`、`write`、`read`和 `close`函数及其用法,解释了文件描述符(fd)的概念,并深入探讨了Linux中的“一切皆文件”思想。这种设计极大地简化了系统编程,使得处理不同类型的IO设备变得更加一致和简单。通过本文的学习,您应该能够更好地理解和应用Linux中的进程IO操作,提高系统编程的效率和能力。
52 34
|
9天前
|
消息中间件 Linux C++
c++ linux通过实现独立进程之间的通信和传递字符串 demo
的进程间通信机制,适用于父子进程之间的数据传输。希望本文能帮助您更好地理解和应用Linux管道,提升开发效率。 在实际开发中,除了管道,还可以根据具体需求选择消息队列、共享内存、套接字等其他进程间通信方
40 16
|
1月前
|
消息中间件 Linux
Linux:进程间通信(共享内存详细讲解以及小项目使用和相关指令、消息队列、信号量)
通过上述讲解和代码示例,您可以理解和实现Linux系统中的进程间通信机制,包括共享内存、消息队列和信号量。这些机制在实际开发中非常重要,能够提高系统的并发处理能力和数据通信效率。希望本文能为您的学习和开发提供实用的指导和帮助。
120 20
|
8月前
|
监控 Linux 应用服务中间件
探索Linux中的`ps`命令:进程监控与分析的利器
探索Linux中的`ps`命令:进程监控与分析的利器
167 13
|
7月前
|
运维 关系型数据库 MySQL
掌握taskset:优化你的Linux进程,提升系统性能
在多核处理器成为现代计算标准的今天,运维人员和性能调优人员面临着如何有效利用这些处理能力的挑战。优化进程运行的位置不仅可以提高性能,还能更好地管理和分配系统资源。 其中,taskset命令是一个强大的工具,它允许管理员将进程绑定到特定的CPU核心,减少上下文切换的开销,从而提升整体效率。
掌握taskset:优化你的Linux进程,提升系统性能
|
7月前
|
弹性计算 Linux 区块链
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
220 4
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
|
6月前
|
算法 Linux 调度
探索进程调度:Linux内核中的完全公平调度器
【8月更文挑战第2天】在操作系统的心脏——内核中,进程调度算法扮演着至关重要的角色。本文将深入探讨Linux内核中的完全公平调度器(Completely Fair Scheduler, CFS),一个旨在提供公平时间分配给所有进程的调度器。我们将通过代码示例,理解CFS如何管理运行队列、选择下一个运行进程以及如何对实时负载进行响应。文章将揭示CFS的设计哲学,并展示其如何在现代多任务计算环境中实现高效的资源分配。