我想在 C 程序中执行 Linux 的终端命令。目前我正在使用system()
函数,但我想使用任何其他system()
函数,因为根据 MISRA 禁止了该函数。
例如,我该如何替换
system("hwclock --systohc --utc");
首先你可以fork()
用来创建一个子进程,然后在子进程中,你可以调用exec()
来执行你想要的命令。
有一个简单的例子:
$ chmod u+x command.sh
$ cat command.sh
#!/usr/bin/env bash
ls -l
************* test.c *************
#include<unistd.h>
int main(void)
{
execl("./command.sh","command.sh",(char*)0);
return 0;
}
这是一个非常有趣的问题。我对 MISRA C 的理解是它为在关键系统中使用 C 语言提供了指导。但是包含该system
函数的 C 语言标准库只是现代应用程序中通常使用的库代码总和的一小部分——通常甚至在嵌入式系统中。
我从未开发过符合 MISRA 标准的应用程序,而且我只能找到稍旧(从 2004 年开始)的 MISRA 指南版本。据我所知,MISRA 对 POSIX 库函数的使用保持沉默,您通常可以在任何类型的基于 Linux 的系统上使用这些函数。如果 MISRA 真的对 POSIX 库函数保持沉默,那么 POSIX 库中的任何函数都应该不受限制。这将包括fork
、exec
和popen
,它们都是由 POSIX 定义的,而不是由 C 语言标准定义的。在这三个中,popen
可能在功能/接口上与 C 函数最相似system
。
也就是说,您可能想问自己为什么 MISRA C 会限制system
函数的使用,以及相同的原理是否也适用于上述三个函数的使用。
使用fork
+exec
系列函数通常是建议的方法,简单的实现很简单,但是我发现它是边缘情况的雷区。
system()
在内部使用 fork + exec 并仅查看glibc 的实现,它的源代码对于处理所有信号处理程序来说是巨大的。但是信号处理程序清除 + 恢复必须以线程安全的方式处理,因此在多线程代码中还需要考虑竞争条件问题,这就是 glib 的代码如此不可读的原因。
如果可用,我建议您使用posix_spawn代替,它对用户更加友好,并且与 posix_spawn 不同system
,它具有更安全的界面。