Linux——进程间通信——system V系列

这篇具有很好参考价值的文章主要介绍了Linux——进程间通信——system V系列。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

 ✅<1>主页::我的代码爱吃辣
📃<2>知识讲解:Linux——进程间通信——system V系列
☂️<3>开发环境:Centos7
💬<4>前言:system V 版本进程间通信的机制。

目录

一.共享内存介绍

 二.共享内存函数

1.shmget函数

 2.shmat函数

 3.shmdt函数

 4.shmctl函数

 三.代码示例

1.Comm.hpp

2.client.cc

3.server.cc

4.测试结果

四. 消息队列

 五.信号量

1.互斥



Linux——进程间通信——system V系列,linux,linux,运维,服务器

system共有三个IPC方案:

  1. System V 共享内存
  2. System V 消息队列
  3. System V 信号量

 今天我们重点讲解 system共享内存。

一.共享内存介绍

共享内存是进程间通信中最简单的方式之一,也是最快的IPC形式,因为进程可以直接读写内存,而不需要任何数据的拷贝 。共享内存允许两个或更多进程访问同一块内存,就如同malloc()函数向不同进程返回了指向同一个物理内存区域的指针。

共享内存在进程空间的映射:使用共享内存通信的一个进程可以将共享内存映射到自己的地址空间中,这样就可以像操作普通变量一样操作这块内存了。另外一个进程也可以通过相同的方式将这块内存映射到自己的地址空间中,然后进行读写操作。

示意图:

Linux——进程间通信——system V系列,linux,linux,运维,服务器

 查看内核中的共享内存使用命令:

ipcs

Linux——进程间通信——system V系列,linux,linux,运维,服务器

 二.共享内存函数

1.shmget函数

功能:用来创建共享内存。
原型:int shmget(key_t key, size_t size, int shmflg)。
参数:

  1. key:这个共享内存段名字。
  2. size:共享内存大小。
  3. shmflg:由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样的。

返回值:成功返回一个非负整数,即该共享内存段的标识码;失败返回-1。

 2.shmat函数

功能:将共享内存段连接到进程地址空间。
原型:void *shmat(int shmid, const void *shmaddr, int shmflg);
参数

  1. shmid: 共享内存标识。
  2. shmaddr:指定连接的地址。
  3. shmflg:它的两个可能取值是SHM_RND和SHM_RDONLY。

返回值:成功返回一个指针,指向共享内存第一个节;失败返回-1 。

说明:

  • shmaddr为NULL,核心自动选择一个地址。
  • shmaddr不为NULL且shmflg无SHM_RND标记,则以shmaddr为连接地址。
  • shmaddr不为NULL且shmflg设置了SHM_RND标记,则连接的地址会自动向下调整为SHMLBA的整数倍。公式:shmaddr -(shmaddr % SHMLBA)。
  • shmflg=SHM_RDONLY,表示连接操作用来只读共享内存。

 3.shmdt函数

功能:将共享内存段与当前进程脱离。
原型:int shmdt(const void *shmaddr);
参数:shmaddr: 由shmat所返回的指针。
返回值:成功返回0;失败返回-1。
注意:将共享内存段与当前进程脱离不等于删除共享内存段。

 4.shmctl函数

功能:用于控制共享内存。
原型:int shmctl(int shmid, int cmd, struct shmid_ds *buf);
参数

  1. shmid:由shmget返回的共享内存标识码。
  2. cmd:将要采取的动作(有三个可取值)。
  3. buf:指向一个保存着共享内存的模式状态和访问权限的数据结构。

返回值:成功返回0;失败返回-1。

Linux——进程间通信——system V系列,linux,linux,运维,服务器

 三.代码示例

基于共享内存实现server,client通信:

1.Comm.hpp

#include <iostream>
#include <cstring>
#include <cerrno>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>

using namespace std;

// 项目路径
const char *pathname = "/home/wq/23_10_1";
// 项目编号
const int pro_id = 0664;
// 共享内存大小
const size_t gsize = 4096;

#define CLIENT 1
#define SERVER 0

class Shm
{
public:
    Shm(int type)
        : _type(type)
    {
        getkey();
        if (_type == 0)
            createshmserver();
        else
            createshmclient();
        hookshm();
    }
    char *getstart()
    {
        return _start;
    }
    ~Shm()
    {
        Leaveshm();

        if (_type == 0)
        {
            sleep(3);
            delshm();
        }
    }

private:
    void To_Hex(key_t k)
    {
        printf("0x%x\n", k);
    }

    // 1.获取唯一共享内存段名字key
    void getkey()
    {
        _key = ftok(pathname, pro_id);
        To_Hex(_key);
        if (_key == -1)
        {
            cerr << "shm:" << errno << ":" << strerror(errno) << endl;
        }
    }

    // 2.创建共享内存
    int createshm(int flag)
    {
        int shmid = shmget(_key, gsize, flag);

        return shmid;
    }

    // 2.1创建共享内存客户端接口
    void createshmclient()
    {
        // 客户端仅仅找到服务端创建的shm
        _shmid = createshm(IPC_CREAT);
        if (_shmid == -1)
        {
            cerr << "client shm create:" << errno << ":" << strerror(errno) << endl;
            exit(2);
        }
    }

    // 2.2创建共享内存服务端接口
    void createshmserver()
    {
        // 创建shm,如果已经存在就报错,不存在创建一个新的共享内存
        _shmid = createshm(IPC_CREAT | IPC_EXCL | 0666);
        if (_shmid == -1)
        {
            cerr << "server shm create:" << errno << ":" << strerror(errno) << endl;
            exit(3);
        }
    }

    // 3.将共享内存段连接到进程地址空间
    void hookshm()
    {
        _start = (char *)shmat(_shmid, NULL, SHM_RND);
        if (_start == NULL)
        {
            cerr << "hookshm:" << errno << ":" << strerror(errno) << endl;
        }
    }

    // 4.将共享内存段与到进程地址空间断开
    void Leaveshm()
    {
        int n = shmdt(_start);
        if (n == -1)
        {
            cerr << "shmdt:" << errno << ":" << strerror(errno) << endl;
        }
    }

    // 5.删除共享内存
    void delshm()
    {
        int n = shmctl(_shmid, IPC_RMID, NULL);
        if (n == -1)
        {
            cerr << "shmdt:" << errno << ":" << strerror(errno) << endl;
        }
    }

private:
    key_t _key;   // 共享内存段名字
    int _shmid;   // 共享内存段的标识码
    char *_start; // 共享内存映射到地址空间的起始地址,将来当作一段malloc的空间使用
    int _type;    // 身份 —— SERVER,CLIENT
};

2.client.cc

#include "Comm.hpp"

int main()
{
    // 1.创建共享内存对象
    Shm shm(CLIENT);
    // 2.得到内存块
    char *start = shm.getstart();
    // 3.读取数据
    while (1)
    {
        sleep(2);
        printf("%s", start);
    }

    return 0;
}

3.server.cc

#include "Comm.hpp"

int main()
{
    // 1.创建共享内存对象
    Shm shm(SERVER);
    // 2.得到内存块
    char *start = shm.getstart();
    // 3.写入数据
    while (1)
    {
        char buff[1024] = {0};
        char *str = fgets(buff, sizeof(buff), stdin);
        buff[strlen(str)] = 0;
        for (int i = 0; i < strlen(str); i++)
        {
            start[i] = buff[i];
        }
        start[strlen(str)] = 0;
    }
    sleep(20);

    return 0;
}

 makefile:

.PHONY:all
all:server client

server:server.cc
	g++ -o $@ $^ -std=c++11

client:client.cc
	g++ -o $@ $^ -std=c++11

.PHONY:clean
clean:
	rm -rf server client 

4.测试结果

Linux——进程间通信——system V系列,linux,linux,运维,服务器

四. 消息队列

  1. 消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法。
  2. 每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值特性方面。
  3. IPC资源必须删除,否则不会自动清除,除非重启,所以system V IPC资源的生命周期随内核。

Linux——进程间通信——system V系列,linux,linux,运维,服务器

 五.信号量

信号量主要用于同步和互斥的,下面先来看看什么是同步和互斥。

1.互斥

  1. 任何一个时刻,都只允许一个执行流在进行共享资源的访问——加锁。
  2. 我们把任何一个时刻,都只允许一个执行流在进行访问的共享资源,叫做临界资源。
  3. 临界资源是要通过代码访问的,凡是访问临界资源的代码,叫做临界区。
  4. 要么不做,要么做完,只有两种确定状态的属性,原子性。
  5. IPC资源必须删除,否则不会自动清除,除非重启,所以system V IPC资源的生命周期随内核。
     

信号量就是对资源的一种预定机制,就像电影院座位和电影票一样。其本身就是一种计数器,信号量有两种操作P操作(申请信号量)计数器++,V操作(释放信号量)计数器--。

进程想要访问临界资源,首先申请信号量(P操作),只要我们申请成功未来一定能得到子资源。

访问完临界资源释放信号量(V操作)。

P,V操作,计数器的++或者--,一定要是原子的。

 文章来源地址https://www.toymoban.com/news/detail-738680.html

到了这里,关于Linux——进程间通信——system V系列的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Linux】进程间通信——System V信号量

    目录 写在前面的话 一些概念的理解 信号量的引入 信号量的概念及使用            System V信号量是一种较低级的IPC机制 ,使用的时候需要手动进行操作和同步。在现代操作系统中,更常用的是 POSIX信号量 (通过 sem_* 系列的函数进行操作)或更高级的同步原语(如互斥锁

    2024年02月11日
    浏览(36)
  • 【Linux】进程间通信——system V共享内存 | 消息队列 | 信号量

    共享内存是一种在多个进程之间进行进程间通信的机制。它允许多个进程访问相同的物理内存区域,从而实现高效的数据交换和通信。 因为 进程具有独立性(隔离性) ,内核数据结构包括对应的代码、数据与页表都是独立的。OS系统为了让进程间进行通信,必须让不同的进

    2024年02月15日
    浏览(41)
  • Linux之进程间通信——system V(共享内存、消息队列、信号量等)

    本文介绍了另一种进程间通信——system V,主要介绍了共享内存,消息队列、信号量,当然消息队列了信号量并非重点,简单了解即可。 共享内存 :不同的进程为了进行通信看到的同一个内存块,该内存块被称为共享内存。 进程具有独立性,它的内核数据结构包括对应的代

    2024年02月08日
    浏览(47)
  • 【探索Linux】—— 强大的命令行工具 P.15(进程间通信 —— system V共享内存)

    在多进程编程中,进程间通信(IPC)是一项关键技术,它使得不同的进程能够相互交换数据和协调行为。而在众多的IPC机制中,System V共享内存是一种高效且强大的通信方式。通过使用共享内存,我们可以将数据从一个进程快速地传递给另一个进程,避免了复制数据的开销,

    2024年02月05日
    浏览(52)
  • Linux终端与进程的关系 ( 1 ) -【Linux通信架构系列】

    C++技能系列 Linux通信架构系列 C++高性能优化编程系列 深入理解软件架构设计系列 高级C++并发线程编程 期待你的关注哦!!! 现在的一切都是为将来的梦想编织翅膀,让梦想在现实中展翅高飞。 Now everything is for the future of dream weaving wings, let the dream fly in reality. 进程之间是一

    2024年02月10日
    浏览(84)
  • 运维 | 查看 Linux 服务器 IP 地址

    大多数在操作 Linux 系统时,我们经常需要知道服务器的 IP 比便于后续的一系列操作,这时候有快速查看主机 IP 的命令行操作,能够有效的帮助我们 本章节主要记录一些常用查看服务器 IP 的命令,希望对大家有所帮助。 查看 Linux 服务器的 IP 地址的命令大体上有以下几种。

    2024年04月27日
    浏览(52)
  • 【运维】Linux 跨服务器复制文件文件夹

    如果是云服务 建议用内网ip scp是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的。可能会稍微影响一下速度。当你服务器硬盘变为只读 read only system时,用scp可以帮你把文件移出来

    2024年02月08日
    浏览(46)
  • 【Linux 服务器运维】定时任务 crontab 详解 | 文末送书

    本文思维导图概述的主要内容: 1.1 什么是 crontab Crontab 是一个在 Unix 和 Linux 操作系统上 用于定时执行任务 的工具。它允许用户创建和管理计划任务,以便在特定的时间间隔或时间点自动运行命令或脚本。Crontab 是 cron table 的缩写, cron 指的是 Unix 系统中的一个后台进程,它

    2024年02月08日
    浏览(62)
  • linux并发服务器 —— 多进程并发(四)

    程序是包含一系列信息的文件,描述了如何在运行时创建一个进程; 进程是正在运行的程序的实例,可以用一个程序来创建多个进程; 用户内存空间包含程序代码以及代码所使用的变量,内核数据结构用于维护进程状态信息; 进程控制块(PCB):维护进程相关的信息,tas

    2024年02月11日
    浏览(40)
  • 【Linux运维】shell脚本检查服务器内存和CPU利用率

    在管理服务器时候写了一个 shell脚本,在服务上实现每天凌晨3点查系统的指定文件夹下的容量大小,如果超过10G就要删除3天前的内容,还要时刻查询内存和cpu利用率,如果超过80%就要提示用户出现过载 将以上代码保存为一个.sh文件,然后通过crontab在每天凌晨3点运行即可:

    2024年02月09日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包