• 微课视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 程序设计
  • 信息安全
微课江湖
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 微课视频
  • bios
  • 系统安装
  • 系统进程
  • Windows
  • LINUX
  • RedHat/Centos
  • Ubuntu/Debian
  • Fedora
  • Solaris
  • 麒麟系统
  • 红旗Linux
  • 苹果MAC
  • 注册表
  • 其它系统
您的位置:首页 > 操作系统 >RedHat/Centos > CentOS下共享内存使用的常见陷阱详解

CentOS下共享内存使用的常见陷阱详解

作者:佚名 字体:[增加 减小] 来源:互联网 时间:2017-05-12

佚名 通过本文向大家介绍了centos分区详解,centos iptables详解,centos 查看内存,centos 虚拟内存,centos 内存等相关知识,希望对您有所帮助,也希望大家多多支持微课江湖

所谓共享内存就是使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。其他进程能把同一段共享内存段“连接到”他们自己的地址空间里去。所有进程都能访问共享内存中的地址。如果一个进程向这段共享内存写了数据,所做的改动会即时被有访问同一段共享内存的其他进程看到。共享内存的使用大大降低了在大规模数据处理过程中内存的消耗,但是共享内存的使用中有很多的陷阱,一不注意就很容易导致程序崩溃。

超过共享内存的大小限制?

在一个linux服务器上,共享内存的总体大小是有限制的,这个大小通过SHMMAX参数来定义(以字节为单位),您可以通过执行以下命令来确定 SHMMAX 的值:

# cat /proc/sys/kernel/shmmax

如果机器上创建的共享内存的总共大小超出了这个限制,在程序中使用标准错误perror可能会出现以下的信息:

unable to attach to shared memory

解决方法:

1、设置 SHMMAX

SHMMAX 的默认值是 32MB 。一般使用下列方法之一种将 SHMMAX 参数设为 2GB :

通过直接更改 /proc 文件系统,你不需重新启动机器就可以改变 SHMMAX 的默认设置。我使用的方法是将以下命令放入 />etc/rc.local 启动文件中:

# echo "2147483648" > /proc/sys/kernel/shmmax

您还可以使用 sysctl 命令来更改 SHMMAX 的值:

# sysctl -w kernel.shmmax=2147483648

最后,通过将该内核参数插入到 /etc/sysctl.conf 启动文件中,您可以使这种更改永久有效:

# echo "kernel.shmmax=2147483648" >> /etc/sysctl.conf

2、设置 SHMMNI

我们现在来看 SHMMNI 参数。这个内核参数用于设置系统范围内共享内存段的最大数量。该参数的默认值是 4096 。这一数值已经足够,通常不需要更改。

您可以通过执行以下命令来确定 SHMMNI 的值:

# cat /proc/sys/kernel/shmmni

4096

3、设置 SHMALL

最后,我们来看 SHMALL 共享内存内核参数。该参数控制着系统一次可以使用的共享内存总量(以页为单位)。简言之,该参数的值始终应该至少为:

ceil(SHMMAX/PAGE_SIZE)

SHMALL 的默认大小为 2097152 ,可以使用以下命令进行查询:

# cat /proc/sys/kernel/shmall

2097152

SHMALL 的默认设置对于我们来说应该足够使用。

注意: 在 i386 平台上 Red Hat Linux 的 页面大小 为 4096 字节。但是,您可以使用 bigpages ,它支持配置更大的内存页面尺寸。

多次进行shmat会出现什么问题?

当首次创建共享内存段时,它并不能被任何进程所访问。为了使共享内存区可以被访问,则必须通过 shmat 函数将其附加( attach )到自己的进程空间中,这样进程就与共享内存建立了连接。该函数声明在 linux/shm.h中:

#include

#include

void *shmat(int shmid, const void *shmaddr, int shmflg);

参数 shmid 是 shmget() 的返回值,是个标识符;

参数 shmflg 是存取权限标志;如果为 0 ,则不设置任何限制权限。在 中定义了几个权限:

#define SHM_RDONLY 010000 /* attach read-only else read-write */

#define SHM_RND 020000 /* round attach address to SHMLBA */

#define SHM_REMAP 040000 /* take-over region on attach */

如果指定 SHM_RDONLY ,那么共享内存区只有读取权限。

参数 shmaddr 是共享内存的附加点,不同的取值有不同的含义:

?如果为空,则由内核选择一个空闲的内存区;如果非空,返回地址取决于调用者是否给 shmflg 参数指定 SHM_RND 值,如果没有指定,则共享内存区附加到由 shmaddr 指定的地址;否则附加地址为 shmaddr 向下舍入一个共享内存低端边界地址后的地址 (SHMLBA ,一个常址)。

Ø通常将参数 shmaddr 设置为 NULL 。

shmat() 调用成功后返回一个指向共享内存区的指针,使用该指针就可以访问共享内存区了,如果失败则返回 -1。

其映射关系如下图所示:

图1.1 共享内存映射图

其中,shmaddr表示的是物理内存空间映射到进程的虚拟内存空间时候,虚拟内存空间中该块内存的起始地址,在使用中,因为我们一般不清楚进程中哪些地址没有被占用,所以不好指定物理空间的内存要映射到本进程的虚拟内存地址,一般会让内核自己指定:

void ptr = shmat(shmid, NULL,0);

这样挂载一个共享内存如果是一次调用是没有问题的,但是一个进程是可以对同一个共享内存多次 shmat进行挂载的,物理内存是指向同一块,如果shmaddr为NULL,则每次返回的线性地址空间都不同。而且指向这块共享内存的引用计数会增加。也就是进程多块线性空间会指向同一块物理地址。这样,如果之前挂载过这块共享内存的进程的线性地址没有被shmdt掉,即申请的线性地址都没有释放,就会一直消耗进程的虚拟内存空间,很有可能会最后导致进程线性空间被使用完而导致下次shmat或者其他操作失败。

解决方法:

可以通过判断需要申请的共享内存指针是否为空来标识是否是第一次挂载共享内存,若是则使用进行挂载,若不是则退出。

void* ptr = NULL;

...

if (NULL != ptr)

return;

ptr = shmat(shmid,ptr,0666);

附:

函数shmat将标识号为shmid共享内存映射到调用进程的地址空间中,映射的地址由参数shmaddr和shmflg共同确定,其准则为:

(1) 如果参数shmaddr取值为NULL,系统将自动确定共享内存链接到进程空间的首地址。

(2) 如果参数shmaddr取值不为NULL且参数shmflg没有指定SHM_RND标志,系统将运用地址shmaddr链接共享内存。

(3) 如果参数shmaddr取值不为NULL且参数shmflg指定了SHM_RND标志位,系统将地址shmaddr对齐后链接共享内存。其中选项SHM_RND的意思是取整对齐,常数SHMLBA代表了低边界地址的倍数,公式“shmaddr – (shmaddr % SHMLBA)”的意思是将地址shmaddr移动到低边界地址的整数倍上。

Shmget创建共享内存,当key相同时,什么情况下会出错?

shmget() 用来创建一个共享内存区,或者访问一个已存在的共享内存区。该函数定义在头文件 linux/shm.h中,原型如下:

#include

#include

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

参数 key是由 ftok() 得到的键值;

参数 size 是以字节为单位指定内存的大小;

参数 shmflg 是操作标志位,它的一些宏定义如下:

IPC_CREATE : 调用 shmget 时,系统将此值与其他共享内存区的 key 进行比较,如果存在相同的 key ,说明共享内存区已存在,此时返回该共享内存区的标识符,否则新建一个共享内存区并返回其标识符。

IPC_EXCL : 该宏必须和 IPC_CREATE 一起使用,否则没意义。当 shmflg 取 IPC_CREATE | IPC_EXCL 时,表示如果发现内存区已经存在则返回 -1,错误代码为 EEXIST 。

注意,当创建一个新的共享内存区时,size 的值必须大于 0 ;如果是访问一个已经存在的内存共享区,则置 size 为 0 。

一般我们创建共享内存的时候会在一个进程中使用shmget来创建共享内存,

Int shmid = shmget(key, size, IPC_CREATE|0666);

而在另外的进程中,使用shmget和同样的key来获取到这个已经创建了的共享内存,

Int shmid = shmget(key, size, IPC_CREATE|0666);

如果创建进程和挂接进程key相同,而对应的size大小不同,是否会shmget失败?

Ø 已经创建的共享内存的大小是可以调整的,但是已经创建的共享内存的大小只能调小,不能调大

如:

shm_id = shmget(key,4194304,IPC_CREAT);

创建了一个4M大小的共享内存,如果这个共享内存没有删掉,我们再使用

shm_id = shmget(key,10485760,IPC_CREAT);

来创建一个10M大小的共享内存的时候,使用标准错误输出会有如下错误信息:

shmget error: Invalid argument

但是,如果我们使用:

shm_id = shmget(key,3145728,IPC_CREAT);

来创建一个3M大小的共享内存的时候,并不会输出错误信息,只是共享内存大小会被修改为3145728,这也说明,使用共享内存的时候,是用key来作为共享内存的唯一标识的,共享内存的大小不能区分共享内存。

这样会导致什么问题?

当多个进程都能创建共享内存的时候,如果key出现相同的情况,并且一个进程需要创建的共享内存的大小要比另外一个进程要创建的共享内存小,共享内存大的进程先创建共享内存,共享内存小的进程后创建共享内存,小共享内存的进程就会获取到大的共享内存进程的共享内存, 并修改其共享内存的大小和内容(留意下面的评论补充),从而可能导致大的共享内存进程崩溃。

解决方法:

方法一:

在所有的共享内存创建的时候,使用排他性创建,即使用IPC_EXCL标记:

Shmget(k

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • centos 联合编译动态连接库详解
  • CentOS 7安装后实用优化详解
  • CentOS的网络配置的命令详解
  • CentOS下的系统负荷详解
  • CentOS分区cfdisk操作详解
  • CentOS 7.1开机运行模式run level详解
  • CentOS常用的文本查看命令详解
  • CentOS下对SSD寿命的检查和健康判断详解
  • 安装Centos 6.5时包组安装建议详解
  • CentOS系统中与时间的相关命令详解

相关文章

  • 2017-05-12通过CentOS 7.0 电源管理关闭笔记本合盖睡眠待机的方法
  • 2017-05-12使用U盘作为载体使用UltraISO软碟通安装Centos6.4
  • 2017-05-12CentOS系统中rpm包管理器的使用技巧
  • 2017-05-12centos:/tmp不能运行导致的安装编译错误问题解决方法
  • 2017-05-12CentOS7如何封停 解封IP?
  • 2017-05-12Linux下如何查看某个软件是否安装???软件的安装路径又在哪???
  • 2017-05-12CentOS下使用yum安装xen 4.2.2教程
  • 2017-05-12haproxy+keepalived负载均衡之主备切换(centos)
  • 2017-05-12CentOS下nethogs命令详解
  • 2017-05-12给VMware虚拟机中的CentOS分区扩容的操作笔记

文章分类

  • bios
  • 系统安装
  • 系统进程
  • Windows
  • LINUX
  • RedHat/Centos
  • Ubuntu/Debian
  • Fedora
  • Solaris
  • 麒麟系统
  • 红旗Linux
  • 苹果MAC
  • 注册表
  • 其它系统

最近更新的内容

    • CentOS下VIM实用基本操作技巧详解
    • CentOS上如何安装配置GitLab?
    • CentOS里egrep命令详解
    • centos7怎么取消锁屏?centos系统取消自动锁屏的教程
    • CentOS救援模式实验笔记详解
    • centos手动释放内存的方法
    • CentOS下vi编辑器用法大全
    • CentOS下ssh如何登录限制ip?CentOS下ssh登录限制ip的方法
    • linux下安装Zend Optimizer的方法
    • centos计算内存CPU正确方法

关于我们 - 联系我们 - 免责声明 - 网站地图 - 投诉建议

©CopyRight 2015-2017 www.weikejianghu.com Inc All Rights Reserved. 微课江湖 版权所有