GDAL的最大波段数限制及最大文件数限制
Posted 深蓝静音
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GDAL的最大波段数限制及最大文件数限制相关的知识,希望对你有一定的参考价值。
最大波段数限制
GDAL写文件时,一个文件最多可以有多少个波段呢?
int nMaxBandCount = atoi(CPLGetConfigOption("GDAL_MAX_BAND_COUNT", "65535"));
printf("Max band count:%d\\n", nMaxBandCount);
我们可以用CPLSetConfigOption来修改这个数值:
//设置最大波段数
CPLSetConfigOption("GDAL_MAX_BAND_COUNT", "65536");
那么这个数值最大能多大呢?
根据源码中的逻辑,在gcore\\gdal_misc.cpp中,GDALCheckBandCount中进行波段数目检查:
int GDALCheckBandCount( int nBands, int bIsZeroAllowed )
if (nBands < 0 || (!bIsZeroAllowed && nBands == 0) )
CPLError(CE_Failure, CPLE_AppDefined,
"Invalid band count : %d", nBands);
return FALSE;
const char* pszMaxBandCount = CPLGetConfigOption("GDAL_MAX_BAND_COUNT", "65536");
/* coverity[tainted_data] */
int nMaxBands = atoi(pszMaxBandCount);
if ( nBands > nMaxBands )
CPLError(CE_Failure, CPLE_AppDefined,
"Invalid band count : %d. Maximum allowed currently is %d. "
"Define GDAL_MAX_BAND_COUNT to a higher level if it is a legitimate number.",
nBands, nMaxBands);
return FALSE;
return TRUE;
其中CPLGetConfigOption的定义如下:
const char * CPL_STDCALL
CPLGetConfigOption( const char *pszKey, const char *pszDefault )
#ifdef DEBUG_CONFIG_OPTIONS
CPLAccessConfigOption(pszKey, TRUE);
#endif
const char *pszResult = NULL;
int bMemoryError = FALSE;
char **papszTLConfigOptions = reinterpret_cast<char **>(
CPLGetTLSEx(CTLS_CONFIGOPTIONS, &bMemoryError));
if( papszTLConfigOptions != NULL )
pszResult = CSLFetchNameValue(papszTLConfigOptions, pszKey);
if( pszResult == NULL )
CPLMutexHolderD(&hConfigMutex);
pszResult =
CSLFetchNameValue(const_cast<char **>(g_papszConfigOptions), pszKey);
if( pszResult == NULL )
pszResult = getenv(pszKey);
if( pszResult == NULL )
return pszDefault;
return pszResult;
可以看到,源码中的逻辑是先从默认设置开始取值,如果没有,从环境变量中取值,否则返回默认值,并且这个值在源码中是一个int型的整数,所以其最大值就是int的最大值2147483647。
根据以上信息可知,除了用CPLSetConfigOption设置最大波段数外,还可以通过环境变量来设置,并且环境变量的优先级最高:
Linux下:
export GDAL_MAX_BAND_COUNT=2147483647
最大文件数量限制
在unix系统下,使用GDALOpen打开ENVI文件,会遇到打开文件数量511个后继续打开就会失败的问题。追查源码就会发现,这个问题的如下:
gcore\\gdaldataset.cpp GDALOpenEx -->
frmts\\raw\\envidataset.cpp ENVIDataset::Open -->
port\\cpl_vsil.cpp VSIFOpenExL -->
port\\cpl_vsil_unix_stdio_64.cpp VSIUnixStdioFilesystemHandler::Open -->
iofopen.c fopen64
最后会发现,是系统的fopen64返回了NULL。系统底层的io函数为啥会返回null呢?
这是因为unix系统对于打开文件的句柄数量有限制,通过ulimit -a就可以看到最大文件数量限制,一般默认1024个,这就是为啥我们打开ENVI格式的文件,到511个就失败了。
ENVI的文件,会打开一个数据文件,同时打开一个头文件,一个文件占用两个fp,所以打开第512个时,读到头文件就1024个了,所以就打开失败了。
针对此问题,可以通过修改unix系统的最大文件数量来解决,不过最好的办法就是不要用GDALOpen缓存这么多的GDALDataset。
ubuntu临时修改文件数量的方法是:
ulimit -SHn 1048576
ulimit 命令身分软限制和硬限制,硬限制就是实际的限制,而软限制是警告限制,它只会给出警告。
加-H就是硬限制,加-S就是软限制。默认显示的是软限制,如果运行ulimit 命令修改时没有加上-H或-S,就是两个参数一起改变。
永久生效的方法是修改文件: sudo vi /etc/security/limits.conf
添加
* soft nofile 65535
* hard nofile 65535
或
sudo echo "* soft nofile 65535" >> /etc/security/limits.conf
sudo echo "* hard nofile 65535" >> /etc/security/limits.conf
上面是一个进程打开文件数量的限制,除此以外,可能还存在系统总的限制,我看查看该限制:
cat /proc/sys/fs/file-max
可以临时修改这个限制:
sudo echo 26336040 > /proc/sys/fs/file-max
临时修改在机器重启后就会失效,要想永久生效,修改配置:
sudo vi /etc/sysctl.conf
加入
fs.file-max = 26336040
以上是关于GDAL的最大波段数限制及最大文件数限制的主要内容,如果未能解决你的问题,请参考以下文章