使用对system()的调用而不是编程语言的函数是否存在缺点?

时间:2015-07-02 12:16:10

标签: c bash system-calls

我在C中编程为嵌入式设备创建一些API。这个嵌入式设备运行Linux的变体。我对C不是很熟悉 - 我对shell脚本/ bash更熟悉。

考虑到这一点,当涉及检查目录是否存在或获取磁盘使用时,我发现只需调用systempopen并执行我的命令就更容易了,然后解析输出。作为开发人员,我的速度更快。

进行这些systempopen调用是否有缺点,而不是在C中找出如何处理这些内容然后再使用C&C的函数?

4 个答案:

答案 0 :(得分:4)

即使它可以在Linux上运行,也不能依赖于您打算使用的所有命令的可用性,因此缺点是直接的:您不能依赖一个给定的工具可用

要考虑的另一件事是从c解析shell命令的输出非常困难。

最后,您无法让程序随机调用系统实用程序或shell脚本,因为它不安全。

答案 1 :(得分:4)

缺点:

  1. 如果有用户输入
  2. 则不安全
  3. 难以解析输出
  4. 它将依赖于外部的东西,例如shell脚本。
  5. 重过程 - 系统fork()并并行启动另一个程序
  6. 优点:

    1. 易于实施
    2. 取决于程序输出解析可能非常容易。示例system("ls -1");
    3. 总结 -

      这取决于你需要做什么,但一般情况下有更多的负面因素而不是正数。

答案 2 :(得分:2)

在一天结束时,在Linux系统上,几乎所有东西都在某个时候调用C函数。

要触及评论中的一些论点以及我自己的想法:

  1. 从c程序执行shell命令,尤其是在使用用户参数时,是一个潜在的漏洞。例如,如果您允许用户使用参数“foo; rm -rf *”调用您的程序;根据你调用shell的方式,如果你想创建用户提供的目录,你可以有效地调用“mkdir foo; rm -rf *”。根据您对用户的信任程度等,这可能也可能不是什么大问题。
  2. 执行shell命令会导致您无法避免的潜在竞争条件,这些条件可能更容易使用您链接在一起的直接系统调用来处理
  3. 解析命令的输出意味着在C中处理更多的字符串操作,这不是很有趣。
  4. 如果您真的更喜欢bash,最好的办法是实现小程序,这些程序包含目标库C API的不连续部分。无论如何,这是UNIX方式(tm)。
  5. 编辑以解决Pimgd的评论:请注意,竞争条件是一个痛苦的问题,其中很多不一定是您的特定用例的问题,但至少在衡量pro / con时是值得考虑的。无论如何,我正在考虑的特定竞争条件实例包括(并且可能还有其他类):

    1. 安全类型的竞争条件。如果您创建包含一组命令的临时文件然后执行它,则有可能在创建和执行之间有人进入并修改该文件。 (对于诸如设置/重置sym链接等内容,这个主题实际上有各种各样的变化)。根据您的上述评论,这几乎超出了您的项目范围,但是对于其他应用程序需要注意。
    2. 多进程竞争条件。我能想到的最简单的例子是,如果程序的两个实例想要设置配置文件并且同时运行,会发生什么。某些操作系统调用对原子性有一定程度的保证,但是如果调用一系列shell命令来写入文件,则会丢失很多。 (请注意,即使您从单片C应用程序而不是一系列shell命令执行此操作,您仍需要做一些额外的操作来防止实例1覆盖实例2的更改,但您至少不会遇到最终混合变化的情况。例如:

      FILE * fp = fopen(“config.txt”,“wt”);

      fprintf(fp,“Config value 1:%s”,config [0]);

      fprintf(fp,“Config value 2:%s”,config [1]);

      fflush(FP);

      FCLOSE(FP);

    3. VS

      system("echo Config value 1: `df | awk '{print $1}'` > config.txt");
      system("echo Config value 2: `ps | grep foo | awk '{print $2}'` >> config.txt");
      

      如果程序的两个实例在接近确切的时间运行,那么最终可以使用例如在后一种情况下,配置文件中有2个Config值为2的实例。

答案 3 :(得分:2)

也许这是一种有效的方法,让你更熟悉shell脚本,就像这样:

使用shell脚本作为基础,执行所有高级计算。该脚本可以使用一个(或多个)命令来寻址API;只提供这些命令,编写小型C程序。

例如:

#!/bin/bash
valueA=$(APIhelper -q valueA)
valueB=$(APIhelper -q valueB)

process() { … }

result=$(process "$valueA" "$valueB")

APIhelper -s result "$result"

如果您了解shell脚本,则应该清楚这一部分。

现在您只需要编写二进制文件APIhelper(请根据您的上下文选择更合适的名称; - )。

这可以是这样的C程序:

int main(int argc, char *argv[]) {
  if (argc > 1) {
    if (strstr(argv[1], "-q") == 0) {
      if (argc > 2) {
        char *variableName = argv[2];
        someType result = makeYourApiCall(variableName);
        printf("%O\n", result);  # use a fitting format instead of %O!
      } else {
        fprintf(stderr, "-q without variable name\n");
        exit(1);
      }
    else if (strstr(argv[1], "-s") == 0) {
      …
    } else {
      fprintf(stderr, "option not understood: %s\n", argv[1]);
      exit(1);
    }
  } else {
    fprintf(stderr, "missing option\n");
    exit(1);
  }
  return 0;
}

这种方式只能在C程序中完成API的最基本处理,您可以坚持使用最佳代码:脚本。此外,通过这种方式,您可以轻松地调试API,因为可以通过交互方式从命令行调用此工具APIhelper