4

scandir() 函数扫描目录 dir,在每个目录条目上调用 select() 作为“int(*filter)(const struct dirent *)” 如何将模式值作为参数传递给 fnmatch(const char *pattern, const char *string, int flags) 过滤器中使用的函数?

这是我的示例代码

int my_selectgrf(const struct dirent *namelist)
{
   int  r = 0;
   char     my_pattern[] = "*.grf";
   r = fnmatch(my_pattern, namelist->d_name, FNM_PERIOD);

   return (r==0)?1:0;
}
scandir("/pub/data/grf", &namelist, my_selectgrf, alphasort);

我的目标是能够使用 my_pattern 作为输入参数。

4

1 回答 1

5

简短的回答:你不能。这是一个非常糟糕的 API,最近在 2008 年(基于 glibc 中的糟糕设计)将类似的东西添加到 POSIX 是完全可耻的。这种无法参数化或传递上下文的 API 应该在 20 多年前被废除。

话虽如此,有一些解决方法:

方法 1:使用全局变量,如果您的代码需要是线程安全的,请通过锁定确保一次只能使用一个线程scandir与给定的扫描函数一起使用。这当然会序列化使用,如果你真的想从多个线程调用函数,这可能是不可接受的。

方法 2:使用线程本地存储,使用 GCC__thread关键字(或 C11_Thread_local关键字,遗憾的是 GCC 仍然不接受)或 POSIXpthread_setspecific和系列。这是相当干净的,但不幸的是它可能不正确;如果scandir内部使用多个线程的实现,则该参数可能无法在某些回调扫描函数中可用。目前,我不相信scandir.

现在,更好的解决方案:

放弃scandir并编写自己的函数来做同样的事情,使用适当的 API。反正只有几行。

于 2013-09-13T08:09:53.107 回答