如何让system()使用通配符

时间:2014-08-27 21:34:01

标签: c beagleboneblack

我正在使用ubuntu。我尝试使用带有外卡的system()函数,每次运行该函数时,它都需要*作为文字。我在系统中使用的命令是echo。看起来像这样。

system("echo cape-bone-iio > /sys/devices/bone_capmgr.*/slots) 

我尝试过它和许多其他东西,但是我不能让这张外卡工作。它返回一个错误:

Sh: 1: cannot create /sys/devices/bone_capemgr.*/slots 

当我通过终端而不是程序

运行它时,它会起作用

我有一个解决方法,它只是循环到0到99,但它占用了比我想要的更多的资源。我知道使用系统命令是不安全的,但我严格用于beaglebone系统。

3 个答案:

答案 0 :(得分:3)

在运行/sys/devices/bone_capmgr.*/slots之前,echo globbing由shell扩展。阅读glob(7)。如果它匹配两个文件(例如,*27),则命令将扩展为:

echo cape-bone-iio > \
  /sys/devices/bone_capmgr.2/slots /sys/devices/bone_capmgr.7/slots

然后你会发现这是无意义的。 (但如果将*扩展为4之类的内容,那将是有意义的。如果没有文件与globbing模式匹配,那么shell可能会创建一个内部带有*的文件名(这会触发cannot create /sys/devices/bone_capemgr.*/slots消息)。

你可能会跑

for f in /sys/devices/bone_capmgr.*/slots ; do \
  echo cape-bone-iio > $f ; \
done

但我不认为将这么长的字符串传递给system总是一个好主意。您可以在C程序中执行for循环(使用/sys/devices/上的opendir(3) + readdir(3) ...},然后您甚至不需要system fopen (使用fprintf ...)循环中只有fclose + readdir + /sys/devices/bone_capmgr.*/slots。您也可以使用glob(3)wordexp(3)

当没有readdir文件存在时,您可能需要处理这种情况,例如因为某些硬件缺失或未连接。

顺便说一下,system(3)调用的shell会扫描像glob(或wordexpsnprintf)这样的目录,所以用手编写该循环可以避免分支shell并且应该稍快一点。

你也可以使用nftw(3),但我认为这对你的需求来说太笼统了。它递归扫描文件树,如find(1)命令。

您还可以使用for (ix=0; ix<100; x++)/proc/循环中生成文件名,并使用access(2)

测试其存在

最后,您可能会通过echo查询这些设备是否存在(如果它暴露了有关您硬件的信息,请参阅proc(5)了解更多信息)。 udev(7)也可能是相关的。

BTW尝试strace(1) shell在终端中解释您的strace /bin/sh -c "echo cape-bone-iio > /sys/devices/bone_capmgr.*/slots"命令(或简称为{{1}}),以找出您的shell使用的syscalls(2)

没有任何shell可以用普通的系统调用来做。

答案 1 :(得分:1)

如果您坚持使用system调用,那么另一个替代方案是find命令:

system( "find /sys/devices/ -type d -name 'bone_capmgr.*'"
         " -exec sh -c 'echo cap-bone-iio > {}/slots' \;"  );

如果有多个匹配glob模式bone_capmgr.*的目录,这将防止注释中提到的模糊重定向错误。

但我建议接受Basile Starynkevitch提供的建议。

答案 2 :(得分:-1)

首先,我必须说你应该直接写文件,而不是产生一个进程来为你做。

话虽如此,你可以做你所要求的 system("sh -c 'echo cape-bone-iio > /sys/devices/bone_capmgr.*/slots'")