LINUX 共享内存越界

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.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;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值