shmget的时候,我们能指定共享内存的size,当size越界的时候,会如何呢?
如下:
/*
* ShareMem.h
*
* Created on: 2013-2-25
* Author: coreycui
*/
#ifndef SHAREMEM_H_
#define SHAREMEM_H_
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
usingnamespacestd;
classShareMem {
public:
ShareMem(int_shmid);
boolcreate(intflag,intlen);
intgetSgmId()const;
char* attach();
booldettach();
virtual~ShareMem();
private:
intshmId;
boolisAttche;
char* addr;
};
#endif /* SHAREMEM_H_ */
/*
* ShareMem.h
*
* Created on: 2013-2-25
* Author: coreycui
*/
#ifndef SHAREMEM_H_
#define SHAREMEM_H_
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
class ShareMem {
public:
ShareMem(int _shmid);
bool create(int flag,int len);
int getSgmId() const;
char* attach();
bool dettach();
virtual ~ShareMem();
private:
int shmId;
bool isAttche;
char* addr;
};
#endif /* SHAREMEM_H_ */
/*
* ShareMem.cpp
*
* Created on: 2013-2-25
* Author: coreycui
*/
#include "ShareMem.h"
ShareMem::ShareMem(int_shmid) :
shmId(_shmid), isAttche(false), addr(0) {
}
boolShareMem::create(intflag,intlen) {
shmId = shmget(IPC_PRIVATE, len, flag);
if(shmId
perror("share mem create error");
}
returntrue;
}
intShareMem::getSgmId()const{
returnshmId;
}
char* ShareMem::attach() {
isAttche =true;
char* addr = (char*) shmat(shmId, 0, 0);
if(addr
perror("share mem attach error");
}
returnaddr;
}
boolShareMem::dettach() {
if(addr == 0 && isAttche) {
if(shmdt(addr) > 0) {
returntrue;
}else{
perror("share mem dettach error");
returnfalse;
}
}
returnfalse;
}
ShareMem::~ShareMem() {
dettach();
}
constoption options[] = { {"len", required_argument, NULL,'l'}, {"action", required_argument, NULL,'a'}, {"id",
required_argument, NULL,'i'}, {"msg", required_argument, NULL,'m'}, { 0, 0, 0, 0 } };
intmain(intargc,char**argv) {
charcFileName[128];
intlen;
intch;
intaction;
intid;
charmsg[10000];
while((ch = getopt_long(argc, argv,":l:a:i:", options, NULL)) != -1) {
switch(ch) {
case'l':
len = atoi(optarg);
break;
case'a':
action = atoi(optarg);
break;
case'i':
id = atoi(optarg);
break;
case'm':
strcpy(msg, optarg);
break;
default:
break;
}
}
cout <
//cout <
ShareMem mem(id);
intlockResult;
if(action == 0) {
mem.create(IPC_CREAT | 0666, len);
}
if(action == 1) {
char* addr = mem.attach();
cout <
cout <
strcpy(addr, msg);
}
if(action == 2) {
char* addr = mem.attach();
cout <
cout <
}
if(action == 3) {
for(inti=0;i<9999;i++){
msg[i]='a';
}
msg[9999]='\0';
char* addr = mem.attach();
cout <
strcpy(addr, msg);
}
cout <
pause();
}
/*
* ShareMem.cpp
*
* Created on: 2013-2-25
* Author: coreycui
*/
#include "ShareMem.h"
ShareMem::ShareMem(int _shmid) :
shmId(_shmid), isAttche(false), addr(0) {
}
bool ShareMem::create(int flag, int len) {
shmId = shmget(IPC_PRIVATE, len, flag);
if (shmId < 0) {
perror("share mem create error");
}
return true;
}
int ShareMem::getSgmId() const {
return shmId;
}
char* ShareMem::attach() {
isAttche = true;
char* addr = (char*) shmat(shmId, 0, 0);
if (addr < (char*) 0) {
perror("share mem attach error");
}
return addr;
}
bool ShareMem::dettach() {
if (addr == 0 && isAttche) {
if (shmdt(addr) > 0) {
return true;
} else {
perror("share mem dettach error");
return false;
}
}
return false;
}
ShareMem::~ShareMem() {
dettach();
}
const option options[] = { { "len", required_argument, NULL, 'l' }, { "action", required_argument, NULL, 'a' }, { "id",
required_argument, NULL, 'i' }, { "msg", required_argument, NULL, 'm' }, { 0, 0, 0, 0 } };
int main(int argc, char **argv) {
char cFileName[128];
int len;
int ch;
int action;
int id;
char msg[10000];
while ((ch = getopt_long(argc, argv, ":l:a:i:", options, NULL)) != -1) {
switch (ch) {
case 'l':
len = atoi(optarg);
break;
case 'a':
action = atoi(optarg);
break;
case 'i':
id = atoi(optarg);
break;
case 'm':
strcpy(msg, optarg);
break;
default:
break;
}
}
cout << "len:" << len << " action:" << action << " id:" << id << " msg:" << msg << endl;
//cout << "pageSize:" << PAGE_SIZE << endl;
ShareMem mem(id);
int lockResult;
if (action == 0) {
mem.create(IPC_CREAT | 0666, len);
}
if (action == 1) {
char* addr = mem.attach();
cout << "sizeof:" << strlen(addr) << endl;
cout << "msg sizeof" << strlen(msg) << endl;
strcpy(addr, msg);
}
if (action == 2) {
char* addr = mem.attach();
cout << "len.addr:" << strlen(addr) << endl;
cout << "addr:" << addr << endl;
}
if (action == 3) {
for(int i=0;i<9999;i++){
msg[i]='a';
}
msg[9999]='\0';
char* addr = mem.attach();
cout << "msg sizeof" << strlen(msg) << endl;
strcpy(addr, msg);
}
cout << lockResult << endl;
pause();
}
之上是对共享内存的封装,首先我们建立一块共享内存:
./shareMem --action=0 --len=2 --msg=helloworld --id=0
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00005feb 0 admin 666 12000 3
0x00005fe7 32769 admin 666 524288 2
0x00005fe8 65538 admin 666 2097152 1
0x0003022a 131075 admin 777 2072 1
0x0003022b 163844 admin 777 5603392 1
0x00030227 196613 admin 777 221248 1
0x73010002 262150 admin 666 8 0
0x29481458 327688 mqq 644 114744 0
0x29481456 360457 mqq 644 11380552 0
0x29481457 393226 mqq 644 8020508 0
0x000033b0 425995 mqq 666 114688 0
0x00000000 589839 coreycui 666 2 0
对数据进行超过两个字节的write:
./shareMem --action=1 --len=2 --msg=helloworld --id=557070
后进行read,发现一切正常。
是不是shm对越界不做判断了?多出的字节写到了哪里呢?其实不然,shm的分配会自动补全到系统的PAGESIZE,32bit的机器上一般都是4096,不妨,我们写入10000字节。果然发生了段错误。所以这里我们必须做出判断。
bool ShareMem::getInfo(shmid_ds* buf) {
return shmctl(this->shmId, IPC_STAT, buf);
}
所以使用之前,我们必须得到内存块的大小,帮助我们更方便和安全的使用这块内存:
if (action == 4) { shmid_ds info; mem.getInfo(&info); cout << "shm seg len:" << info.shm_segsz << endl; }