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

How to pass parameters and use them using exec in C?

我想从我的每个子进程开始一个新进程,并让它们添加通过 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);
}

显示的代码中存在很多很多问题:

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

    • 不要写在根目录。
    • 不要 运行 作为 root。
    • 只有 root 应该能够在根目录中写入。
    • 运行 因为 root 是有风险的,应该避免。
  • 不要使用看起来像源代码的名称来调用您的可执行程序 — EXEC.c 通常是 C 源文件,而不是可以执行的程序;您需要从 EXEC.c.
  • 创建和 运行 EXEC
  • 有些人会添加 "don't shout" — 大多数情况下,程序名称都是 lower-case,或者大部分是 lower-case;如图所示,它们很少 upper-case。
  • 在这种情况下,编译 exec.c 以创建 exec 会工作 很糟糕 好吧 因为 即使 exec 是 built-in shell 命令,不在磁盘上搜索。 使用 /path/to/exec(甚至 ./exec)会起作用,但某些路径(至少一个 /)是必需的。 因为您使用 execv(),内核(不是shell)会直接执行程序。但是,您仍应使用不同的名称 — 可能会造成混淆。
  • 也不要使用 test 作为您的程序的名称 — 那是另一个 shell built-in,调用您自己的程序 test 会很快或稍后,通常会更快。
  • 请参阅 What should main() return in C and C++ — 您应该使用 int main(void)int main(int argc, char **argv)(有趣的是,您应该在 code.c 中使用较短的变体而在 [=14 中使用较长的变体=],但你把它们倒过来了)。
  • 您通过 argcargv 访问传递给程序的参数——参数是字符串。
  • 您将参数作为字符串传递给执行的程序,而不是像您尝试使用 static char *argv[]={a,b,NULL}; 那样传递给执行的程序的参数(其中 ab 的类型为 int).如果不是由此产生的错误,您应该会收到编译器警告。
  • 您应该将程序名称作为 argv[0] 传递,并将操作参数作为 argv[1]argv[2] 传递——您将 NULL 添加到末尾是正确的参数列表。
  • 您不应该在 code.c 中包括所有您能想到的 headers — 您应该只包括您使用的那些。
  • 你不应该重复 <stdio.h><stdlib.h>
  • 你的间距应该保持一致——最好遵循第一个 #include <stdio.h> line 的模式(#include 之间没有 space;一个 space 在 include<stdio.h> 之间;通常没有尾随的白色 space,但如果认为有益的话允许评论,并且应该在白色 space 之前)。
  • EXEC.c 中的 printf() 应该在格式字符串的末尾有一个换行符。
  • forking() 中的代码无法编译,因为 for 循环的 body 是 pid_t pID = fork(); — 而且您不能将变量定义为body 没有大括号的循环。此外,pID 不会为 if 语句定义,除非它也在循环的 body 中。另外,ab 的定义没有以分号结尾。
  • 你应该在 execv() 之后有一个 exit() 之类的,最好也有错误信息,以防 execv() 失败。
  • wait() 的调用是错误的 — wait() 需要一个 int 指针参数,而不是普通的 int

可能还有其他问题需要解决。下面修改后的代码是两个文件,parent.cchild.c。该代码假定 child 程序在当前目录中(因此 ./child 将执行它)。你运行parent;它创建了 child 个进程。

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;
}

严格来说,代码应该检查 strtol() 是否有效,但正确地执行此操作很繁琐 - 请参阅 Correct usage of strtol()? 了解更多详细信息。

示例输出

$ ./parent
9
Process 14201 exited with status 0x0000
9
Process 14202 exited with status 0x0000
9
Process 14203 exited with status 0x0000
9
Process 14204 exited with status 0x0000
$