IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 【linux 共享内存 】 -> 正文阅读

[系统运维]【linux 共享内存 】

概念

  • 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存。共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式。不同进程之间共享的内存通常安排为同一段物理内存。进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是由用C语言函数malloc()分配的内存一样。而如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程。
  • 特别提醒:共享内存并未提供同步机制,也就是说,在第一个进程结束对共享内存的写操作之前,并无自动机制可以阻止第二个进程开始对它进行读取。所以我们通常需要用其他的机制来同步对共享内存的访问,例如前面说到的信号量。有关信号量的更多内容,可以查阅另一篇文章

API

1.shmget函数

#include <sys/ipc.h>
#include <sys/shm.h>

函数

int shmget(key_t key, size_t size, int shmflg);

参数

key : 0(IPC_PRIVATE) 会建立新共享内存对象
大于032位整数:视参数shmgflag来确定操作,通常要求此值来源于ftok返回的IPC键值

size:大于0的整数:新建的共享内存的大小,以字节为单位
0:只获取共享内存时指定为0

shmflg: 0 取共享内存标识符,若不存在则报错
shmflg是权限标志,它的作用与open函数的mode参数一样,如果要想在key标识的共享内存不存在时,创建它的话,
可以与IPC_CREAT做或操作。共享内存的权限标志与文件的读写权限一样,举例来说,0644,它表示允许一个进程
创建的共享内存被内存创建者所拥有的进程向共享内存读取和写入数据,同时其他用户创建的进程只能读取共享内存。
IPC_CREAT:当shmflg&IPC_CREAT为真时,如果内核中不存在与key相等的共享内存,则新建一个共享内存,如果
存在这样的共享内存,则返回共享内存的标识符。
IPC_CREAT|IPC_EXCL:如果内核中不存在键值与key相等的共享内存,则新建一个共享内存:如果存在这样的共享
内存则报错

返回值

成功则返回共享内存的标识符,失败则返回-1,错误存在errno中
EINVAL:参数size小于SHMMIN或大于SHMMAX
EEXIST:预建立key所指的共享内存,但已经存在
EIDRM:参数key所指的共享内存已经删除
ENOSPC:超过了系统允许建立的共享内存的最大值(SHMALL)
ENOENT:参数key所指的共享内存不存在,而参数shmflg未设IPC_CREAT位
EACCES:没有权限
ENOMEM:核心内存不足

2.shmat函数

函数

void *shmat(int shmid, const void *shmaddr, int shmflg);
shmat()是用来允许本进程访问一块共享内存的函数,与shmget()函数共同使用。第一次创建完共享内存时,它还不能被
任何进程访问,shmat()函数的作用就是用来启动对该共享内存的访问,并把共享内存连接到当前进程的地址空间。共享内
存(Shared Memory)就是允许多个进程访问同一个内存空间,是在多个进程之间共享和传递数据最高效的方式。操作
系统将不同进程之间共享内存安排为同一段物理内存,进程可以将共享内存连接到它们自己的地址空间中,如果某个进程
修改了共享内存中的数据,其它的进程读到的数据也将会改变。

参数

shm_id是由shmget函数返回的共享内存标识。
shm_addr指定共享内存连接到当前进程中的地址位置,通常为空,表示让系统来选择共享内存的地址。
shm_flg是一组标志位,通常为0

返回值

调用成功时返回一个指向共享内存第一个字节的指针,如果调用失败返回-1.

3.shmdt函数

该函数用于将共享内存从当前进程中分离。注意,将共享内存分离并不是删除它,只是使该共享内存对当前进程不再可用。它的原型如下:
int shmdt(const void *shmaddr);
参数shmaddr是shmat()中的参数shmaddr地址指针,调用成功时返回0,失败时返回-1.

4.shmctl函数

函数

int shmctl(int shm_id, int command, struct shmid_ds *buf);

参数

第一个参数,shm_id是shmget()函数返回的共享内存标识符。
第二个参数,command是要采取的操作,它可以取下面的三个值 :
IPC_STAT:把shmid_ds结构中的数据设置为共享内存的当前关联值,即用共享内存的当前关联值覆盖shmid_ds的值。
IPC_SET:如果进程有足够的权限,就把共享内存的当前关联值设置为shmid_ds结构中给出的值
IPC_RMID:删除共享内存段
第三个参数,buf是一个结构指针,它指向共享内存模式和访问权限的结构。
shmid_ds结构 至少包括以下成员:

struct shmid_ds
{
    uid_t shm_perm.uid;
    uid_t shm_perm.gid;
    mode_t shm_perm.mode;
};

返回值

成功返回0,失败返回-1

例程:

//
// Created by Administrator on 2022/4/21.
//信号量示例
#include "_public.h"      //包含所有需要的头文件

CSEM sem;           //用于给共享内存加锁的信号量

struct st_pid
{
    int pid;     //进程编号
    char name[51]; //进程名称
};


int main(int argc,char *argv[])
{
    int shmid;  //0x5005 十六进制  key
    //申请一段共享内存
    if ((shmid = shmget(0x5005,sizeof(struct st_pid),0640|IPC_CREAT)) == -1)
    {
        printf("shmget(0x5005) failed \n");
        return -1;
    }
    //使用命令 ipcs -m 查看共享内存
    //命令 ipcrm -m shimd  删除共享内存



    //把共享内存连接到当前进程的地址空间
    // void* shmat(int shmid, const void *shmaddr, int shmflg);
    //函数返回值 共享内存地址   shmid 共享内存id  其他参数为0

    //用于指向共享内存的结构体变量
    struct st_pid * stPid =0;
    if ((stPid =(struct st_pid *)shmat(shmid,0,0)) == (void*)-1)
    {
        printf("shmat failed\n");
        return -1;
    }

    //下边代码的数据均为共享内存

    printf("pid = %d,name = %s\n",stPid->pid,stPid->name);
    //将当前进程的pid name赋值给结构体
    stPid->pid  = getpid();
    sleep(10);
    strcpy(stPid->name,argv[1]);
    printf("pid = %d,name = %s\n",stPid->pid,stPid->name);

    //ipcs -s 查看信号量id
    //ipcrm sem semid  删除信号量



    //把共享内存从当前进程中分离
    shmdt(stPid);


    //删除共享内存
//    if (shmctl(shmid,IPC_RMID,0) == -1)
//    {
//        printf("shmat failed\n");
//        return -1;
//    }
    return 0;
}
运行两次 
执行   :  ./sharemem aaa
结果:
pid = 0,name =
pid = 27302,name = aaa
    
执行   :  ./sharemem bbb
结果:
pid = 27302,name = aaa
pid = 28787,name = bbb
说明两次运行修改的是同一个结构体指针stpid

-----------.com

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-05-07 11:29:31  更:2022-05-07 11:30:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 17:37:43-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码