关于setrlimit RLIMIT_STACK的一点说明

setrlimit用于限制进程资源使用,其中RLIMIT_STACK是限制栈大小的。
若栈大小超过了限制的大小,则进程会崩溃。

下面代码,设置栈大小为1024字节,然后后面又定义了2 * 1024的数组,并在print也定义了2 * 1024的数组,但是程序并没有崩溃。

#include <sys/resource.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUF_LEN 2  * 1024

void print(){
	printf("enter print function\n");
	int i;
	int length = BUF_LEN;
	char szBuf[BUF_LEN];
	for(i = 0; i < length; i++)
	{
		szBuf[i] = i;
	}
}

int main()
{
	struct rlimit rlimit;
	int ret = 0;
	int i = 0;
	int stackSize = 1  * 1024;
	printf("hello world\n");
	ret = getrlimit(RLIMIT_STACK, &rlimit);
	if(ret < 0)
	{
		printf("getrlimit failed\n");
		return -1;
	}
	rlimit.rlim_cur = stackSize;
	rlimit.rlim_max = stackSize;
	ret = setrlimit(RLIMIT_STACK, &rlimit);
	if(ret < 0)
    {
        printf("setrlimit failed\n");
        return -1;
    }
	printf("setrlimit succeed\n");
	char szBuf[BUF_LEN];
	int length = BUF_LEN;
	for(i = 0; i < length; i++)
	{
		szBuf[i] = i;
	}
	printf("print\n");
	print();
	while(1);
	
	return 0;
}

通过/proc/pid/limits可以看到设置是成功的,但是程序并未崩溃。
加粗样式

后面将BUF_LEN改成2 * 1024 * 1024,stackSize设置为1 * 1024 * 1024。
运行结果为:
在这里插入图片描述
可以看到进程崩溃了,但是可以看其打印,print是打印出来的,而在print函数调用前面,有个char szBuf[BUF_LEN]的栈变量。这说明崩溃的时候,是在调用print时崩溃的(调用print时,首先会进行栈检查)。不是在main函数里面崩溃的。

其实设置RLIMIT_STACK,并不能修改当前函数调用栈帧的限制。main函数栈帧的限制在编译的时候就确定了,是8M。其生效是在后面的函数调用生成的栈帧中生效。故main函数中设置的栈大小为1M,在后面的函数print中生效。而print函数中定义了2M大小的栈变量szBuf,在main函数真正调用print时,会先进行栈限制检查。很明显未通过检查,崩溃。

class getEnvVariableWork(): def __init__(self): self.msgCtrlObj = setEnvMsg("Start to check work directory valid or not") def getWorkDir(self): self.curWorkPath = os.getcwd() reInfo = "(.*)\/" + options.vrfDirName + "\/(\w+)\/(.*)$" curWorkObj = re.match(reInfo,self.curWorkPath) if curWorkObj: self.curProjPath = curWorkObj.group(1) self.curBlockPath= curWorkObj.group(2) self.curWrokPath = curWorkObj.group(3) if self.curWrokPath != "work" and options.localSimCtrl==False: self.msgCtrlObj.warnMsgPrint("the normal project, simulation start excute from work directory") os.environ[options.projTopName] = self.curProjPath elif options.selfDefineWork: self.msgCtrlObj.infoMsgPrint("Simulation scripts will current directory excute") elif options.pathCheckCtrl: self.curProjPath = os.getenv(options.projTopName) else: self.msgCtrlObj.errorMsgPrint("no surport excute the scripts in current directory, if you want, please enable --self=Ture") def getEnvInfo(self): return self.curProjPath+"/"+options.vrfDirName+"/"+self.curBlockPath, self.curBlockPath, self.curWorkPath def setSynEnv(self): self.envPath = os.getenv("PATH") self.vcsHome = "/edatools/synopsys/VCS" self.verdiHome = "/edatools/synopsys/Verdi" self.setPathStr = self.vcsHome + "/bin:" + self.envPath self.setVerdiPathStr = self.verdiHome + "/bin:" + self.envPath os.environ["VCS_HOME"] = self.vcsHome os.environ["NOVAS_HOME"] = self.verdiHome os.environ["VERDI_HOME"] = self.verdiHome os.environ["PATH"] = self.setPathStr os.environ["PATH"] = self.setVerdiPathStr def setCdnEnv(self): self.envPath = os.getenv("PATH") self.ldPath = os.getenv("LD_LIBRARY_PATH") self.cdsLicFile = "/edatools/tools_setup/lic/cadence_20240819.dat" self.xlmHome = "/edatools/cadence/XCELIUM" self.verdiHome = "/edatools/synopsys/Verdi" self.setXlmStr = self.xlmHome + "/bin:" + self.xlmHome + "/tools/bin:" + self.xlmHome + "/tools/dfII/bin:" self.setPathStr = self.setXlmStr + self.envPath self.setLdPathStr= self.xlmHome + "%0s/tools/lib:%0s/share/PLI/IUS/linux64:%0s"%(self.xlmHome,self.verdiHome,self.ldPath) os.environ["CDS_LIC_FILE"] = self.cdsLicFile os.environ["PATH"] = self.setPathStr os.environ["LD_LIBRARY_PATH"] = self.setLdPathStr def setResourceLimit(self): resource.setrlimit(resource.RLIMIT_STACK,(resource.RLIM_INFINITY,resource.RLIM_INFINITY)) resource.setrlimit(resource.RLIMIT_AS,(resource.RLIM_INFINITY,resource.RLIM_INFINITY)) resource.setrlimit(resource.RLIMIT_DATA,(resource.RLIM_INFINITY,resource.RLIM_INFINITY))
08-27
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值