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;
}

相关文章
|
2月前
|
缓存 监控 Linux
Linux内存问题排查命令详解
Linux服务器卡顿?可能是内存问题。掌握free、vmstat、sar三大命令,快速排查内存使用情况。free查看实时内存,vmstat诊断系统整体性能瓶颈,sar实现长期监控,三者结合,高效定位并解决内存问题。
201 0
Linux内存问题排查命令详解
|
5月前
|
监控 Shell Linux
Linux进程控制(详细讲解)
进程等待是系统通过调用特定的接口(如waitwaitpid)来实现的。来进行对子进程状态检测与回收的功能。
119 0
|
5月前
|
存储 负载均衡 算法
Linux2.6内核进程调度队列
本篇文章是Linux进程系列中的最后一篇文章,本来是想放在上一篇文章的结尾的,但是想了想还是单独写一篇文章吧,虽然说这部分内容是比较难的,所有一般来说是简单的提及带过的,但是为了让大家对进程有更深的理解与认识,还是看了一些别人的文章,然后学习了学习,然后对此做了总结,尽可能详细的介绍明白。最后推荐一篇文章Linux的进程优先级 NI 和 PR - 简书。
168 0
|
5月前
|
存储 Linux Shell
Linux进程概念-详细版(二)
在Linux进程概念-详细版(一)中我们解释了什么是进程,以及进程的各种状态,已经对进程有了一定的认识,那么这篇文章将会继续补全上篇文章剩余没有说到的,进程优先级,环境变量,程序地址空间,进程地址空间,以及调度队列。
118 0
|
5月前
|
Linux 调度 C语言
Linux进程概念-详细版(一)
子进程与父进程代码共享,其子进程直接用父进程的代码,其自己本身无代码,所以子进程无法改动代码,平时所说的修改是修改的数据。为什么要创建子进程:为了让其父子进程执行不同的代码块。子进程的数据相对于父进程是会进行写时拷贝(COW)。
139 0
|
8月前
|
Linux 数据库 Perl
【YashanDB 知识库】如何避免 yasdb 进程被 Linux OOM Killer 杀掉
本文来自YashanDB官网,探讨Linux系统中OOM Killer对数据库服务器的影响及解决方法。当内存接近耗尽时,OOM Killer会杀死占用最多内存的进程,这可能导致数据库主进程被误杀。为避免此问题,可采取两种方法:一是在OS层面关闭OOM Killer,通过修改`/etc/sysctl.conf`文件并重启生效;二是豁免数据库进程,由数据库实例用户借助`sudo`权限调整`oom_score_adj`值。这些措施有助于保护数据库进程免受系统内存管理机制的影响。
|
8月前
|
Linux Shell
Linux 进程前台后台切换与作业控制
进程前台/后台切换及作业控制简介: 在 Shell 中,启动的程序默认为前台进程,会占用终端直到执行完毕。例如,执行 `./shella.sh` 时,终端会被占用。为避免不便,可将命令放到后台运行,如 `./shella.sh &`,此时终端命令行立即返回,可继续输入其他命令。 常用作业控制命令: - `fg %1`:将后台作业切换到前台。 - `Ctrl + Z`:暂停前台作业并放到后台。 - `bg %1`:让暂停的后台作业继续执行。 - `kill %1`:终止后台作业。 优先级调整:
559 5
|
运维 关系型数据库 MySQL
掌握taskset:优化你的Linux进程,提升系统性能
在多核处理器成为现代计算标准的今天,运维人员和性能调优人员面临着如何有效利用这些处理能力的挑战。优化进程运行的位置不仅可以提高性能,还能更好地管理和分配系统资源。 其中,taskset命令是一个强大的工具,它允许管理员将进程绑定到特定的CPU核心,减少上下文切换的开销,从而提升整体效率。
掌握taskset:优化你的Linux进程,提升系统性能
|
弹性计算 Linux 区块链
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
468 4
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
|
算法 Linux 调度
探索进程调度:Linux内核中的完全公平调度器
【8月更文挑战第2天】在操作系统的心脏——内核中,进程调度算法扮演着至关重要的角色。本文将深入探讨Linux内核中的完全公平调度器(Completely Fair Scheduler, CFS),一个旨在提供公平时间分配给所有进程的调度器。我们将通过代码示例,理解CFS如何管理运行队列、选择下一个运行进程以及如何对实时负载进行响应。文章将揭示CFS的设计哲学,并展示其如何在现代多任务计算环境中实现高效的资源分配。