linux 共享内存什么时候可以linux访问共享目录

关于linux 共享内存的问题_百度知道linux下多进程访问共享内存队列同步的问题
[问题点数:40分,结帖人zhengsoftware]
linux下多进程访问共享内存队列同步的问题
[问题点数:40分,结帖人zhengsoftware]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
2013年7月 Linux/Unix社区大版内专家分月排行榜第二2012年6月 Linux/Unix社区大版内专家分月排行榜第二2011年5月 Linux/Unix社区大版内专家分月排行榜第二2011年4月 Linux/Unix社区大版内专家分月排行榜第二2011年3月 Linux/Unix社区大版内专家分月排行榜第二2010年10月 Linux/Unix社区大版内专家分月排行榜第二2010年9月 Linux/Unix社区大版内专家分月排行榜第二
2011年9月 Linux/Unix社区大版内专家分月排行榜第三2010年12月 Linux/Unix社区大版内专家分月排行榜第三2010年11月 Linux/Unix社区大版内专家分月排行榜第三2010年9月 C/C++大版内专家分月排行榜第三
2013年6月 Linux/Unix社区大版内专家分月排行榜第二2013年5月 Linux/Unix社区大版内专家分月排行榜第二2013年3月 Linux/Unix社区大版内专家分月排行榜第二2013年1月 Linux/Unix社区大版内专家分月排行榜第二2012年12月 Linux/Unix社区大版内专家分月排行榜第二2012年8月 Linux/Unix社区大版内专家分月排行榜第二2011年12月 Linux/Unix社区大版内专家分月排行榜第二2011年10月 C/C++大版内专家分月排行榜第二2011年10月 Linux/Unix社区大版内专家分月排行榜第二
2012年6月 C/C++大版内专家分月排行榜第三2012年6月 PHP大版内专家分月排行榜第三2012年5月 C/C++大版内专家分月排行榜第三2012年3月 Linux/Unix社区大版内专家分月排行榜第三2012年2月 Linux/Unix社区大版内专家分月排行榜第三2011年11月 C/C++大版内专家分月排行榜第三
2013年6月 Linux/Unix社区大版内专家分月排行榜第二2013年5月 Linux/Unix社区大版内专家分月排行榜第二2013年3月 Linux/Unix社区大版内专家分月排行榜第二2013年1月 Linux/Unix社区大版内专家分月排行榜第二2012年12月 Linux/Unix社区大版内专家分月排行榜第二2012年8月 Linux/Unix社区大版内专家分月排行榜第二2011年12月 Linux/Unix社区大版内专家分月排行榜第二2011年10月 C/C++大版内专家分月排行榜第二2011年10月 Linux/Unix社区大版内专家分月排行榜第二
2012年6月 C/C++大版内专家分月排行榜第三2012年6月 PHP大版内专家分月排行榜第三2012年5月 C/C++大版内专家分月排行榜第三2012年3月 Linux/Unix社区大版内专家分月排行榜第三2012年2月 Linux/Unix社区大版内专家分月排行榜第三2011年11月 C/C++大版内专家分月排行榜第三
本帖子已过去太久远了,不再提供回复功能。今天遇到一个悲剧性的问题,折磨了我两个多小时。
关于linux下共享内存方式进程通讯时,以root权限执行程序创建了一块共享内存,再用非root用户访问这块共享内存是无法访问到的。这个问题有很多可能性,我把我遇到的问题记录在这里,希望后来人少走弯路。
1. 创建共享内存时,shmget函数的第三个参数是关于创建方式及创建权限的,其中该参数的后9位表示权限,对于root创建的共享内存,如果要让其他用户读取,需要将权限设置为0666,即shmget(.., .., IPC_CREATE|0666),其中0表示拥有者ID,第一个6表示创建用户的权限,第二个表示同组用户权限,第三个表示其他用户权限,这里都设置为可读可写了。
2. 创建的共享内存没有释放。对于创建的共享内存不是直接ctrl+c停止程序就可以释放了的,需要调用函数shmctl来释放该共享内存,此处释放意即删除的意思。
原始场景:
& root用户创建共享内存,访问apache调用cgi程序访问共享内存,失败!后来发现apache的进程用户是apache,企图更改进程用户未遂,于是回头看shmget本身的使用方法,还真发现问题了。
阅读(...) 评论()说起共享内存,一般来说会让人想起下面一些方法:1、多线程。线程之间的内存都是共享的。更确切的说,属于同一进程的线程使用的是同一个地址空间,而不是在不同地址空间之间进行内存共享;2、父子进程间的内存共享。父进程以MAP_SHARED|MAP_ANONYMOUS选项mmap一块匿名内存,fork之后,其子孙进程之间就能共享这块内存。这种共享内存由于受到进程父子关系的限制,一般较少使用;3、mmap文件。多个进程mmap到同一个文件,实际上就是大家在共享文件page&cache中的内存。不过文件牵涉到磁盘的读写,用来做共享内存显然十分笨重,所以就有了不跟磁盘扯上关系的内存文件,也就是我们这里要讨论的tmpfs和shmem;
tmpfs是一套虚拟的文件系统,在其中创建的文件都是基于内存的,机器重启即消失。shmem是一套ipc,通过相应的ipc系统调用shmget能够以指定key创建一块的共享内存。需要使用这块内存的进程可以通过shmat系统调用来获得它。虽然是两套不同的接口,但是在内核里面的实现却是同一套。shmem内部挂载了一个tmpfs分区(用户不可见),shmget就是在该分区下获取名为"SYSV${key}"的文件。然后shmat就相当于mmap这个文件。所以我们接下来就把tmpfs和shmem当作同一个东西来讨论了。
tmpfs/shmem是一个介于文件和匿名内存之间的东西。一方面,它具有文件的属性,能够像操作文件一样去操作它。它有自己inode、有自己的page&cache;另一方面,它也有匿名内存的属性。由于没有像磁盘这样的外部存储介质,内核在内存紧缺时不能简单的将page从它们的page&cache中丢弃,而需要swap-out;(参阅《》)
对tmpfs/shmem内存的读写,就是对page&cache中相应位置的page所代表的内存进行读写,这一点跟普通的文件映射没有什么不同。如果进程地址空间的相应位置尚未映射,则会建立到page&cache中相应page的映射;如果page&cache中的相应位置还没有分配page,则会分配一个。当然,由于不存在磁盘上的源数据,新分配的page总是空的(特别的,通过read系统调用去读一个尚未分配page的位置时,并不会分配新的page,而是共享ZERO_PAGE);如果page&cache中相应位置的page被回收了,则会先将其恢复;
对于第三个&如果&,tmpfs/shmem和普通文件的page回收及其恢复方式是不同的:page回收时,跟普通文件的情况一样,内核会通过prio_tree反向映射找到映射这个page的每一个page&table,然后将其中对应的pte清空。不同之处是普通文件的page在确保与磁盘同步(如果page为脏的话需要刷回磁盘)之后就可以丢弃了,而对于tmpfs/shmem的page则需要进行swap-out。注意,匿名page在被swap-out时,并不是将映射它的pte清空,而是得在pte上填写相应的swap_entry,以便知道page被换出到哪里去,否则再需要这个page的时候就没法swap-in了。而tmpfs/shmem的page呢?page&table中对应的pte被清空,swap_entry会被存放在page&cache的radix_tree的对应slot上。
等下一次访问触发page&fault时,page需要恢复。普通文件的page恢复跟page未分配时的情形一样,需要新分配page、然后根据映射的位置重新从磁盘读出相应的数据;而tmpfs/shmem则是通过映射的位置找到radix_tree上对应的slot,从中得到swap_entry,从而进行swap-in,并将新的page放回page&cache;
这里就有个问题了,在page&cache的radix_tree的某个slot上,怎么知道里面存放着的是正常的page?还是swap-out后留下的swap_entry?如果是swap_entry,那么slot上的值将被加上RADIX_TREE_EXCEPTIONAL_ENTRY标记(值为2)。swap_entry的值被左移两位后OR上RADIX_TREE_EXCEPTIONAL_ENTRY,填入slot。也就是说,如果${slot}&&&RADIX_TREE_EXCEPTIONAL_ENTRY&!=&0,则它代表swap_entry,且swap_entry的值是${slot}&&&&2;否则它代表page,${slot}就是指向page的指针,当然其值可能是NULL,说明page尚未分配。那么显然,page的地址值其末两位肯定是0,否则就可能跟RADIX_TREE_EXCEPTIONAL_ENTRY标记冲突了;而swap_entry的值最大只能是30bit或62bit(对应32位或64位机器),否则左移两位就溢出了。
最后以一张图说明一下匿名page、文件映射page、tmpfs/shmem&page的回收及恢复过程:
阅读(...) 评论()使用其他账号登录
一、共享内存相关知识
所谓共享内存,就是多个进程间共同地使用同一段物理内存空间,它是通过将同一段物理内存映射到不同进程的虚拟空间来实现的。由于映射到不同进程的虚拟空间中,不同进程可以直接使用,不需要像消息队列那样进行复制,所以共享内存的效率很高。共享内存可以通过mmap()映射普通文件机制来实现,也可以System V共享内存机制来实现,System V是通过映射特殊文件系统shm中的文件实现进程间的共享内存通信,也就是说每个共享内存区域对应特殊文件系统shm中的一个文件。
二、共享内存原理
System V共享内存把所有共享数据放在共享内存区,任何想要访问该数据的进程都必须在本进程的地址空间新增一块内存区域,用来映射存放共享数据的物理内存页面。System V共享内存通过shmget函数获得或创建一个IPC共享内存区域,并返回相应的标识符,内核在保证shmget获得或创建一个共享内存区,初始化该共享内存区相应的shmid_kernel结构,同时还将在特殊文件系统shm中创建并打开一个同名文件,并在内存中建立起该文件的相应的dentry及inode结构,新打开的文件不属于任何一个进程,所有这一切都是系统调用shmget函数完成的。
三、sysctl.conf 配置文件
以上两段说明部分是从互联网中找到的理解的内容。而做为Linux系统维护人员,能接触到的与共享内存相关的设置主要在/etc/sysctl.conf中的几个配置项。具体如下:
kernel.shmmax = 4
kernel.shmall =
kernel.shmmni = 4096
以下是redhat6官方提供的一份安装oracle的文档关于共享内存的部分介绍,如下:
完整版的redhat官方文档可以
注:需要注意的是free -m命令的输出里也有一项shared,不过通过查看多台主机发现,这项都是0,后来查找资料确认在free命令里共享内存这项已经废弃,没有什么用了。所以共享内存的查看不可以通过该项确认。
四、ipcs与ipcrm
ipcs是Linux下显示进程间通信设施状态的工具。可以显示消息队列、共享内存和信号量的信息。对于程序员非常有用,普通的系统管理员一般用不到此指令。
$ipcs -m 查看系统使用的IPC共享内存资源
$ipcs -q 查看系统使用的IPC队列资源
$ipcs -s 查看系统使用的IPC信号量资源
$ipcs -l 查看系统参数配置
默认不加参数时,使用的参数是
-a (all,显示所有)
输出示例如下:
------ Message Queues --------
used-bytes
------ Shared Memory Segments --------
0x6c04c831 294912
------ Semaphore Arrays --------
0x7a04c831 1245184
使用ipcrm 命令来清除IPC资源:这个命令同时会将与ipc对象相关联的数据也一起移除。当然,只有root用户,或者ipc对象的创建者才有这项权利;
ipcrm -M shmkey
移除用shmkey创建的共享内存段
ipcrm -m shmid
移除用shmid标识的共享内存段
ipcrm -Q msgkey
移除用msqkey创建的消息队列
ipcrm -q msqid
移除用msqid标识的消息队列
ipcrm -S semkey
移除用semkey创建的信号
ipcrm -s semid
移除用semid标识的信号
ipcs与ipcrm配合清理使用的资源的示例如下:
ipcs -q | awk '{ print "ipcrm -q "$2}' | sh & /dev/null 2&&1;
ipcs -m | awk '{ print "ipcrm -m "$2}' | sh & /dev/null 2&&1;
ipcs -s | awk '{ print "ipcrm -s "$2}' | sh & /dev/null 2&&1;
ipcs的其他应用
使用ipcs还可以用以确认某个用户是否存在消息队列的堆积:
1、查询消息队列
------ Message Queues --------
used-bytes
2、找出messages大于0的队列
$ ipcs -q |grep user1 |awk '{if($5&0) print $0}'
0x1579324 user1
0x1644862 user1
0x1677631 user1
0x1710400 user1
五、为什么需要手动释放共享内存
Linux中通过API函数shmget创建的共享内存一般都是在程序中使用shmctl来释放的,但是有时为了调试程序,开发人员可能通过Ctrl + C等方式发送中断信号来结束程序,此时程序申请的共享内存就不能得到释放,当然如果程序没有改动的话,重新运行程序时仍然会使用上次申请的共享内存,但是如果我们修改了程序,由于共享内存的大小不一致等原因会导致程序申请共享内存错误。因此,我们总是希望每次结束时就能释放掉申请的共享内存。
有两种方法可以用来释放共享内存:
第一种:如果总是通过Crtl+C来结束的话,可以做一个信号处理器,当接收到这个信号的时候,先释放共享内存,然后退出程序。
第二种:不管你以什么方式结束程序,如果共享内存还是得不到释放,那么可以通过linux命令ipcrm shm shmid来释放,在使用该命令之前可以通过ipcs -m命令来查看共享内存。
来源:运维之路
原文:http://t.cn/RtbDVXo
版权:本文版权归原作者所有
本文来自微信公众账号提交,由微信啦收录,转载请注明出处。
微信扫码 分享文章}

我要回帖

更多关于 多个线程访问共享内存 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信