shmget的时候,我们能指定共享内存的size,当size越界的时候,会如何呢?
如下:
- /*
- * ShareMem.h
- *
- * Created on: 2013-2-25
- * Author: coreycui
- */
- #ifndef SHAREMEM_H_
- #define SHAREMEM_H_
- #include <sys/ipc.h>
- #include <sys/shm.h>
- #include <sys/types.h>
- #include <error.h>
- #include <string.h>
- #include <unistd.h>
- #include <getopt.h>
- #include <limits.h>
- #include <iostream>
- #include <string.h>
- 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.h
*
* Created on: 2013-2-25
* Author: coreycui
*/
#ifndef SHAREMEM_H_
#define SHAREMEM_H_
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <error.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include <limits.h>
#include <iostream>
#include <string.h>
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) {
- }
- 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.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;
}