如何在C中使用exec传递参数并使用它们?

时间:2019-09-30 03:43:05

标签: c exec

我想从每个子进程中开始一个新进程,并让它们对通过exec()作为参数传递的数字进行加法运算。这样的事情。我只是不知道如何在新过程中访问参数。

code.c

#include <stdio.h>
#include <stdlib.h>
# include <unistd.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <time.h>
# include <stdlib.h>
# include <dirent.h>
# include <stdio.h>
# include <string.h>
# include <getopt.h>
# include<stdbool.h>
# include <ctype.h>
# include<sys/wait.h>
# include<signal.h>
# include <sys/mman.h>
# include<sys/time.h>

void forking()
{ int a=4,b=5
for (int i=0;i<4;i++)
pid_t pID = fork();

                   if (pID == 0)  
                   {
                    static char *argv[]={a,b,NULL};
                                    execv("/EXEC.c",argv);
                   } 
                   else
                     wait(pID);

}

void main(int argc, char **argv)
{
    forking();
}

EXEC.c

#include <stdio.h>
#include <stdlib.h>
# include <stdio.h>
# include <string.h>
int main()
{
    //Code to add a and b and print the sum
    printf("%d",a+b);
}

1 个答案:

答案 0 :(得分:3)

显示的代码中有很多很多问题:

  • 它无法编译。
  • 您不应该在根目录中写入/EXEC.c

    • 不要写在根目录中。
    • 不要以root用户身份运行。
    • 只有root才能在根目录中写入。
    • 以root身份运行具有风险,应该避免。
  • 请勿使用看起来像源代码的名称来调用可执行程序-EXEC.c通常是C源文件,而不是可以执行的程序;您需要从EXEC创建并运行EXEC.c
  • 有些人会添加“不要大喊大叫”-程序名称通常都是小写,或者大多是小写;如图所示,它们很少是大写的。
  • 在这种情况下,即使exec.c是内置的,编译exec来创建exec也会很困难 OK 因为在外壳上未在磁盘上搜索的命令。 使用/path/to/exec(甚至是./exec)是可行的,但是某些路径(至少一个/)是必需的。因为您使用execv() ,内核(而不是外壳程序)将直接执行程序。但是,您仍然应该使用其他名称-存在混淆的范围。
  • 也不要使用test作为您的程序的名称-这是另一个内置的shell,调用您自己的程序test会导致迟早(通常是早晚)的混乱。
  • 请参见What should main() return in C and C++-您应该使用int main(void)int main(int argc, char **argv)(有趣的是,您应该在code.c中使用较短的变体,而在EXEC.c中使用较长的变体,但您将它们向后移。)
  • 您可以访问通过argcargv传递给程序的参数,这些参数是字符串。
  • 您将参数作为字符串传递给执行的程序,而不是像尝试使用static char *argv[]={a,b,NULL};那样传递给纯整数(其中ab的类型为int) 。如果不是这样,您应该得到编译器警告。
  • 您应该将程序名称传递为argv[0],将操作参数传递为argv[1]argv[2] —您可以在参数末尾添加NULL列表。
  • 您不应在code.c中包含所有可以想到的标头,而应仅包含您使用的标头。
  • 您不应重复<stdio.h><stdlib.h>
  • 您应该保持间距一致-最好遵循第一个#include <stdio.h> line的模式(#include之间没有空格; include和{{ 1}};通常不会在结尾加上空格,不过如果认为有帮助,则允许发表评论,并且应在空格后加上空格。
  • <stdio.h>中的printf()应该在格式字符串的末尾带有换行符。
  • EXEC.c中的代码无法编译,因为forking()循环的主体是for —并且,如果没有包围,就不能将变量定义作为循环的主体大括号。此外,除非在循环主体中也没有为pid_t pID = fork();语句定义pID。另外,ifa的定义不是以分号结尾。
  • b之后,您应该有一个exit(),最好还有一条错误消息,以防execv()失败。
  • execv()的调用有误-wait()期望使用wait()指针参数,而不是简单的int

也许还有其他问题在传递中得到解决。下面的修订代码是两个文件intparent.c。该代码假定child.c程序位于当前目录中(因此child将执行它)。您运行./child;它创建子进程。

parent

parent.c

#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> static void forking(void) { for (int i = 0; i < 4; i++) { pid_t pID = fork(); if (pID == 0) { static char *args[] = { "./child", "4", "5", NULL }; execv(args[0], args); fprintf(stderr, "Failed to execute %s\n", args[0]); exit(EXIT_FAILURE); } else if (pID < 0) { fprintf(stderr, "Failed to fork()\n"); exit(EXIT_FAILURE); } else { int corpse; int status; while ((corpse = wait(&status)) > 0) { printf("Process %d exited with status 0x%.4X\n", corpse, status); if (corpse == pID) break; } } } } int main(void) { forking(); return 0; }

child.c

严格来说,代码应该检查#include <stdio.h> #include <stdlib.h> int main(int argc, char **argv) { if (argc != 3) { fprintf(stderr, "Usage: %s number1 number2\n", argv[0]); exit(EXIT_FAILURE); } long number1 = strtol(argv[1], 0, 0); long number2 = strtol(argv[2], 0, 0); printf("%ld\n", number1 + number2); return 0; } 是否有效,但是这样做的确很愚蠢-有关更多详细信息,请参见Correct usage of strtol()?

样本输出

strtol()