LINUX 共享内存越界

shmget的时候,我们能指定共享内存的size,当size越界的时候,会如何呢?

如下:


  1. /* 
  2.  * ShareMem.h 
  3.  * 
  4.  *  Created on: 2013-2-25 
  5.  *      Author: coreycui 
  6.  */  
  7.   
  8. #ifndef SHAREMEM_H_   
  9. #define SHAREMEM_H_   
  10.   
  11. #include <sys/ipc.h>   
  12. #include <sys/shm.h>   
  13. #include <sys/types.h>   
  14. #include <error.h>   
  15. #include <string.h>   
  16. #include <unistd.h>   
  17. #include <getopt.h>   
  18. #include <limits.h>   
  19. #include <iostream>   
  20. #include <string.h>   
  21.   
  22. using namespace std;  
  23.   
  24.   
  25. class ShareMem {  
  26. public:  
  27.     ShareMem(int _shmid);  
  28.     bool create(int flag,int len);  
  29.     int getSgmId() const;  
  30.     char* attach();  
  31.     bool dettach();  
  32.     virtual ~ShareMem();  
  33. private:  
  34.     int shmId;  
  35.     bool isAttche;  
  36.     char* addr;  
  37. };  
  38.   
  39. #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_ */



  1. /* 
  2.  * ShareMem.cpp 
  3.  * 
  4.  *  Created on: 2013-2-25 
  5.  *      Author: coreycui 
  6.  */  
  7.   
  8. #include "ShareMem.h"   
  9.   
  10. ShareMem::ShareMem(int _shmid) :  
  11.         shmId(_shmid), isAttche(false), addr(0) {  
  12. }  
  13.   
  14. bool ShareMem::create(int flag, int len) {  
  15.     shmId = shmget(IPC_PRIVATE, len, flag);  
  16.     if (shmId < 0) {  
  17.         perror("share mem create error");  
  18.     }  
  19.     return true;  
  20. }  
  21.   
  22. int ShareMem::getSgmId() const {  
  23.     return shmId;  
  24. }  
  25.   
  26. char* ShareMem::attach() {  
  27.     isAttche = true;  
  28.     char* addr = (char*) shmat(shmId, 0, 0);  
  29.     if (addr < (char*) 0) {  
  30.         perror("share mem attach error");  
  31.     }  
  32.     return addr;  
  33. }  
  34.   
  35. bool ShareMem::dettach() {  
  36.     if (addr == 0 && isAttche) {  
  37.         if (shmdt(addr) > 0) {  
  38.             return true;  
  39.         } else {  
  40.             perror("share mem dettach error");  
  41.             return false;  
  42.         }  
  43.     }  
  44.     return false;  
  45. }  
  46.   
  47. ShareMem::~ShareMem() {  
  48.     dettach();  
  49. }  
  50.   
  51. const option options[] = { { "len", required_argument, NULL, 'l' }, { "action", required_argument, NULL, 'a' }, { "id",  
  52.         required_argument, NULL, 'i' }, { "msg", required_argument, NULL, 'm' }, { 0, 0, 0, 0 } };  
  53.   
  54. int main(int argc, char **argv) {  
  55.     char cFileName[128];  
  56.     int len;  
  57.     int ch;  
  58.     int action;  
  59.     int id;  
  60.     char msg[10000];  
  61.     while ((ch = getopt_long(argc, argv, ":l:a:i:", options, NULL)) != -1) {  
  62.         switch (ch) {  
  63.         case 'l':  
  64.             len = atoi(optarg);  
  65.             break;  
  66.         case 'a':  
  67.             action = atoi(optarg);  
  68.             break;  
  69.         case 'i':  
  70.             id = atoi(optarg);  
  71.             break;  
  72.         case 'm':  
  73.             strcpy(msg, optarg);  
  74.             break;  
  75.         default:  
  76.             break;  
  77.         }  
  78.     }  
  79.   
  80.     cout << "len:" << len << " action:" << action << " id:" << id << " msg:" << msg << endl;  
  81.     //cout << "pageSize:" << PAGE_SIZE << endl;   
  82.     ShareMem mem(id);  
  83.     int lockResult;  
  84.     if (action == 0) {  
  85.         mem.create(IPC_CREAT | 0666, len);  
  86.     }  
  87.     if (action == 1) {  
  88.         char* addr = mem.attach();  
  89.         cout << "sizeof:" << strlen(addr) << endl;  
  90.         cout << "msg sizeof" << strlen(msg) << endl;  
  91.         strcpy(addr, msg);  
  92.     }  
  93.   
  94.     if (action == 2) {  
  95.         char* addr = mem.attach();  
  96.         cout << "len.addr:" << strlen(addr) << endl;  
  97.         cout << "addr:" << addr << endl;  
  98.     }  
  99.   
  100.     if (action == 3) {  
  101.         for(int i=0;i<9999;i++){  
  102.             msg[i]='a';  
  103.         }  
  104.         msg[9999]='\0';  
  105.         char* addr = mem.attach();  
  106.         cout << "msg sizeof" << strlen(msg) << endl;  
  107.         strcpy(addr, msg);  
  108.     }  
  109.     cout << lockResult << endl;  
  110.     pause();  
  111. }  
/*
 * 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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值