http://blog.csdn.net/jnu_simba/article/details/8917076
进程地址空间和物理地址
http://www.kerneltravel.net/journal/v/mem.htm
linux内存管理
top命令解释
http://wenku.baidu.com/view/d1727f0c76c66137ee061981.html
内存映射(mmap)是Linux操作系统的一个很大特色,它可以将系统内存映射到一个文件(设备)上,以便可以通过访问文件内容来达到访问内存的目的。
mmap将一个文件或者其它对象映射进内存。
http://www.ibm.com/developerworks/cn/linux/l-ipc/part5/index1.html
得到映射普通文件的大小介于一个页面与两个页面之间(大小为:pagesize*2-99),版本1的被映射部分是整个文件
的基础上,
思考 在父子进程 通过mmap匿名映射,实验共享的时候最多可以打开多大空间,修改程序fork.cpp
得到结果
access page 1 over
access page 1 edge over, now begin to access page 2
access page 2 over
access page 2 over
access page 2 edge over, now begin to access page 3
access page 3 over
access page 3 over
access page 3 edge over, now begin to access page 4
access page 4 over
access page 4 over
access page 4 edge over, now begin to access page 5
access page 5 over
access page 5 over
access page 5 edge over, now begin to access page 6
娈甸敊璇?
[root@localhost yis]# child read: the 1 people's age is 20
child read: the 2 people's age is 21
child read: the 3 people's age is 22
child read: the 4 people's age is 23
child read: the 5 people's age is 24
child read: 1 people's age is 100
child page 1 read over
child read: 2 people's age is 100
child page 2 read over
child read: 3 people's age is 100
child page 3 read over
child read: 4 people's age is 100
child page 4 read over
child read: 5 people's age is 100
child page 5 read over
得到,开辟空间的大小介于4个页面与5个页面之间(大小为:pagesize*5-99),
24k左右的空间,内存不受影响
key_t ftok( const char * fname, int id )
系统建立IPC通讯 (消息队列、信号量和共享内存) 时必须指定一个ID值。通常情况下,该id值通过ftok函数得到。
程序a .cpp b.cpp产生进程间的通信
http://blog.csdn.net/muge0913/article/details/7342653
shmget 共享内存
http://blog.csdn.net/icechenbing/article/details/7715472
系统V共享内存是随内核持续的,即使所有访问共享内存的进程都已经正常终止,共享内存区仍然存在(除非显式删
除共享内存),在内核重新引导之前,对该共享内存区域的任何改写操作都将一直保留。
MemControl.h
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <vector>
#include <iostream>
using namespace std;
#define IPCKEY 0x366378
#define MEMSIZE 1024*1024 //MEMSIZE要随IPCKEY一同改变
#define MEMNUM 150 //开辟空间的块数
typedef struct
{
int file_no;
char agen[10];
} st_setting;
class MemControl
{
public:
vector < int > m_OnlyNum; //存储唯一的一串数字
vector < int > m_VecShm_id; //唯一数字对应的id
vector < st_setting * > m_VecPSetting; //存储共享空间在当前进程,每一块的首地址
bool GetNum(); //用ftok获取的一串唯一数字
bool Init(); //开辟空间,如果空间已经开辟就获取id和地址
bool WriteMem(); //在空间位置写数据
bool ReadMem( ); //读取空间数据
bool ClearMem(); //清除空间
};
MemControl.cpp
#include "MemControl.h"
//MemControl::MemControl()
//{}
//MemControl::~MemControl()
//{}
bool
MemControl::GetNum()
{
for(int i=1;i<=MEMNUM;i++)
{
//int var;
// var=ftok(".",i);
m_OnlyNum.push_back( IPCKEY+i );
}
return true;
}
bool
MemControl::Init( )
{ GetNum();
int shm_id;
st_setting * p_setting;
for( vector<int>::iterator iter=m_OnlyNum.begin();iter!=m_OnlyNum.end();++iter)
{
shm_id=shmget( *iter ,MEMSIZE,0640|IPC_CREAT );
if( shm_id==-1 )
{
printf("shmget error,please change the IPCKEY \n");
return false;
}
p_setting=(st_setting*)shmat(shm_id,NULL,0);
m_VecPSetting.push_back(p_setting);
m_VecShm_id.push_back(shm_id);
}
return true;
}
bool
MemControl::WriteMem()
{
int a=0;
string b;
for( vector<st_setting*>::iterator iter=m_VecPSetting.begin(); iter!=m_VecPSetting.end(); ++iter )
{ a=a+1;
cout<<a<<"=="<<endl;
if(1==a)
b="yis A ";
else if(2==a)
b="yis B";
else if(3==a)
b="yis C";
else if(4 ==a)
b="yis D";
else if(5==a)
b="yis E";
else if(6==a)
b="yis F";
else if(7==a )
b="yis G";
else if(8==a)
b="yis H";
else if(9==a)
b="yis I";
else if(10==a)
b="yis J";
else
b="数值大于10";
for( int i=0;i< (MEMSIZE)/sizeof(st_setting) ; i++)
{
// (*iter+i)->agen = b; //这样赋值会错误?
cout<<"===="<<b<<endl;
strncpy((*iter+i)->agen,b.c_str() ,10);
cout<< "写入的agen: "<<( *iter+i )->agen <<endl;
(*iter+i)->file_no = i;
// sleep(1);
printf( "file_no:%d\n",( *iter+i )->file_no );
printf("当前地址%d\n",(*iter+i) );
}
}
return true;
}
bool
MemControl::ReadMem()
{
for( vector<st_setting *>::iterator iter=m_VecPSetting.begin(); iter!=m_VecPSetting.end(); ++iter )
{
for(int i=0;i<(MEMSIZE)/sizeof(st_setting);i++)
{
printf("The value is :%d\n",( *iter+i )->file_no);
printf("当前地址%d\n",(*iter+i) );
cout<<( *iter+i )->agen<<endl;
// sleep(1);
}
}
return true;
}
bool
MemControl::ClearMem()
{
for( vector<st_setting *>::iterator iter=m_VecPSetting.begin(); iter!=m_VecPSetting.end(); ++iter )
{
if(shmdt(*iter) == -1)
{
return false;
perror(" detach error ");
}
}
// 删除共享内存
for( vector<int>::iterator iter=m_VecShm_id.begin(); iter!=m_VecShm_id.end(); ++iter )
{
if (shmctl( *iter , IPC_RMID , NULL ) == -1)
{
perror(" delete error ");
return false;
}
}
return true;
}
writetest.cpp
#include "MemControl.h"
int main()
{
MemControl A;
A.Init();
A.WriteMem();
}
readtest.cpp
#include "MemControl.h"
int main()
{
MemControl A;
A.Init();
A.ReadMem();
}
clearmem.cpp
#include "MemControl.h"
int main()
{
MemControl A;
A.Init();
A.ClearMem();
}
以上是用shm相关函数来控制内存,读写进程共享内存,达到128M的空间
1、系统V共享内存中的数据,从来不写入到实际磁盘文件中去;而通过mmap()映射普通文件实现的共享内存通信可以
指定何时将数据写入磁盘文件中。 注:系统V共享内存机制实际是通过shm文件系统中的文件
实现的,shm文件系统的安装点在交换分区上,系统重新引导后,所有的内容都丢失。
2、系统V共享内存是随内核持续的,即使所有访问共享内存的进程都已经正常终止,共享内存区仍然存在(除非显式删
除共享内存),在内核重新引导之前,对该共享内存区域的任何改写操作都将一直保留。
3、通过调用mmap()映射普通文件进行进程间通信时,一定要注意考虑进程何时终止对通信的影响。而通过系统V共享
内存实现通信的进程则不然。
以上是 http://blog.csdn.net/icechenbing/article/details/7715472
的总结
dev/shm/是linux下一个非常有用的目录,因为这个目录不在硬盘上,而是在内存里。因此在linux下,就不需要大费周折去建 ramdisk,直接使用/dev/shm/就可达到很好的优化效果。/dev /shm/需要注意的一个是容量问题,在linux下,它默认最大为内存的一半大小,使用df -h命令可以看到。但它并不会真正的占用这块内存,如果/dev/shm/下没有任何文件,它占用的内存实际上就是0字节;如果它最大为1G,里头放有 100M文件,那剩余的900M仍然可为其它应用程序所使用,但它所占用的100M内存,是绝不会被系统回收重新划分的,否则谁还敢往里头存文件呢?
默认系统就会加载/dev/shm ,它就是所谓的tmpfs,有人说跟ramdisk(虚拟磁盘),但不一样。象虚拟磁盘一样,tmpfs 可以使用您的 RAM,但它也可以使用您的交换分区来存储。而且传统的虚拟磁盘是个块设备,并需要一个 mkfs 之类的命令才能真正地使用它,tmpfs 是一个文件系统,而不是块设备;您只是安装它,它就可以使用了。
tmpfs有以下优势:
1,动态文件系统的大小。
2,tmpfs 的另一个主要的好处是它闪电般的速度。因为典型的 tmpfs 文件系统会完全驻留在 RAM 中,读写几乎可以是瞬间的。
3,tmpfs 数据在重新启动之后不会保留,因为虚拟内存本质上就是易失的。所以有必要做一些脚本做诸如加载,绑定的操作。
其他详细tmpfs操作:http://www.oschina.net/question/12_79565
http://blog.163.com/qimo601@126/blog/static/15822093201332755551363/
QSystemSemaphore使用