本帖最后由 am3359 于 2018-1-18 17:02 编辑
//我用STM32F407+FATFS+freeRTOS搭建的系统,需要遍历存储器中每个文件夹和文件,常用的办法是递归调用,遍历函数内嵌套自己直到找到每个文件或文件夹。由于目录深度不可控,这个方法有大量的压栈和出栈容易造成栈溢出系统崩溃。
//现采用目录深度可控的非递归方法如下:
#define LEVEL 8 //LEVEL设置大小代表遍历的深度,8就代表8层,内存足够的话可以设置更大些
u8 j,m;
u8 l[LEVEL]; //l[]保存每层文件夹长度,返回上级目录时用
DIR dir_a[LEVEL]; //FATFS使用的目录结构,只有这个比较占内存需要LEVEL*36字节
tbuf[64]; //注意tbuf的大小要能放得下最深的文件名绝对路径
m = 0;
j = 1;
printf("当前目录:
%s:
", tbuf);
while(1) {
if ( j > m ) { //只有搜索子目录时才执行
f_opendir(&dir_a[j-1], (TCHAR*)tbuf);
l[j-1] = strlen((char *)tbuf);
}
m = j;
f_readdir(&dir_a[j-1], &fileinfo); //读取当前目录下的一个文件
if (fileinfo.fname[0] == 0) { //到末尾了,退出
if (j>1) j--; //下个循环进入父目录
else break;
tbuf[l[j-1]] = ' '; //存储的路径返回上级目录
} else {
sprintf((char *)tbuf,"%s/%s",tbuf,*fileinfo.lfname ? fileinfo.lfname : fileinfo.fname);//搜索到的文件或文件名连接成完整的路径
if (fileinfo.fattrib & AM_DIR) { //是目录
printf("%s [%dD]
", tbuf,j); //打印目录
if (j<8) j++; //下个循环进入子目录
} else {
printf("%s [%dF]
", tbuf,j); //打印文件
tbuf[l[j-1]] = ' '; //存储的路径返回目录
}
}
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
void test( void )
{
int i = 0; // 这个i需要保存
char acFileName[256]; // 这个buffer不需要保存。可以定义为全局的,或者根函数申请一个然后通过参数传下来,这样就不占用堆栈了。
while( 1 )
{
i ++; // 本层循环计数
GetName( acFileName ); // buffer打印完就没用了
printf( "%s %d", acFileName, i );
if( strlen( acFileName ) == 0 )
{
return;
}
test();
}
}
上面那个函数每次递归都要占用256字节的buffer,改成下面这样,只在main中申请一个256字节就可以了。
void test( char *pcFileName )
{
int i = 0; // 这个i需要保存
while( 1 )
{
i ++; // 本层循环计数
GetName( pcFileName); // buffer打印完就没用了
printf( "%s %d", pcFileName, i );
if( strlen( pcFileName) == 0 )
{
return;
}
test( pcFileName );
}
}
int main( void )
{
char acFileName[256]; // 这个buffer不需要保存。可以定义为全局的,或者根函数申请一个然后通过参数传下来,这样就不占用堆栈了。
test( acFileName );
}
在FreeRTOS里运行一次系统就死了
FRESULT scan_files (char* path)
{
FRESULT res;
u32 i[8],j;
char fn[64],tmppath[64];
strcpy((char *)tmppath,(char *)path);
for(j=0;j<8;j++) {
res = f_opendir(&dir, (TCHAR*)tmppath);
if (res == FR_OK) {
i[j] = strlen(tmppath);
{
res = f_readdir(&dir, &fileinfo);
if (res != FR_OK || fileinfo.fname[0] == 0) break;
if (fileinfo.fname[0] == '.') continue;
strcpy((char *)fn,*fileinfo.lfname ? fileinfo.lfname : fileinfo.fname);
if (fileinfo.fattrib & AM_DIR) {//是目录
strcat(tmppath,"/");
strcat(tmppath,fn);
printf("%s ", tmppath);
res = scan_files(tmppath);
if (res != FR_OK) break;
tmppath[i[j]] = 0;
} else {
printf("%s/%s ", tmppath, fn);
}
}
}
}
return res;
}
脑子不够用,怎么改让它不死??
一周热门 更多>