0

我正在编写一个程序来从命令行(linux/unix 命令)获取用户输入,并在我的程序中执行它们。

到目前为止我的步骤:

  1. 询问用户输入的命令数
  2. fork() 创建子进程
  3. 输出子 PID 和父 PID
  4. 允许用户输入每个命令,将每个输入读入 argv 的索引
  5. 使用 execv 在 argv 中运行每个命令

主要问题是当它执行时,它只是执行 execv 命令中的“bin/ls/”。

这是运行我的程序的示例输出:

输入命令数:2
孩子的 PID 是 3487。父母的 PID 是 3485
输入 UNIX 命令:ls
输入 UNIX 命令:-al

文件列表,就像在 CMD 上键入“LS”一样LINE

处理完成。


这是我的源代码:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>

void main(int argc, char *argv[20])
{
        int pid;
        int num = 0;

        printf("Enter number of commands: ");
        scanf("%d", &argc);

        pid = fork();

        if(pid == 0)
        {
                printf("Child's PID is %d. Parent's PID is %d\n", (int)getpid(), (int)getppid());

                for(num=0; num < argc; num++)
                {
                        printf("Enter a UNIX command: ");
                        scanf("%s", argv[num]);
                }

                argv[num+1] = 0;

                execv("bin/ls/", argv);
        }
        else
        {
                wait(pid);
                printf("Process Complete.\n");
                exit(0);
        }
}
4

3 回答 3

0

char* argv[20]首先,您要定义main哪个不是一个好主意。如果您传入超过 20 个参数,您将超出数组的范围。

其次,您试图将一个字符串读scanf("%s", argv[num])入一个据我所知尚未初始化的地址空间。

“字符串”的 argv[] 数组在调用您的程序时由操作系统初始化,如果您不向程序传递任何参数,您将没有任何“字符串”,这意味着您将写入随机存储器你可能不拥有。

如果您真的想以现在的方式加载命令,请尝试以下操作:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>

void main(int argc, char *argv[])
{
    int pid;
    int num = 0;
    int argc2 = 0;
    char* argv2[20]; // argv2 will point inside of buffer for convenience.
    char* buffer[2000]; // note each array has a limit of 100 characters.

    printf("Enter number of commands: ");
    scanf("%d", &argc2);

    pid = fork();

    if(pid == 0)
    {
            printf("Child's PID is %d. Parent's PID is %d\n", (int)getpid(), (int)getppid());

            for(num=0; num < argc2 && num < 20; num++) // your array is 20 long
            {
                    argv2[num] = &buffer[num * 100];
                    printf("Enter a UNIX command: ");
                    scanf("%s", argv2[num]);
            }

            argv[num] = 0; // no need to add + 1 because the for loop did already anyway.

            execv("Assignments/ls", argv2);
    }
    else
    {
            wait(pid);
            printf("Process Complete.\n");
            exit(0);
    }
}

或者,您可以将参数传递给主程序,主程序只需将它们传递给被调用的程序,如下所示:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>

void main(int argc, char *argv[])
{
    int pid;
    int num = 0;

    printf("You entered %d commands: \n", argc);

    for (num = 0; num < argc; ++num)
    {
        printf("\t%s\n", argv[num]);
    }

    pid = fork();

    if(pid == 0)
    {
            printf("Child's PID is %d. Parent's PID is %d\n", (int)getpid(), (int)getppid());

            execv("Assignments/ls", &argv[1]);
    }
    else
    {
            wait(pid);
            printf("Process Complete.\n");
            exit(0);
    }
}
于 2012-09-21T23:33:15.427 回答
0

您的代码存在的一个具体问题是您必须将 argv[idx] 作为参数传递给 exec。通过传递 argv,您正在传递一个 char 指针数组。

还请注意 argc 包含参数的完整计数,并且完整计数包括程序本身。argv[0] 包含您要向其传递参数的程序名称。我没有看到这反映在你的 for 循环中。那就是您正在处理自己的程序并运行它。

我写这些的方法是在一段时间内(或者,如果你愿意的话)遍历 argv,使用一个 int 变量——例如int idx=0;——直到我找到一个为空的 argv[idx] 指针。

例如,如果您有三个参数,则 argc 将为 4,而 argv[3] 将是您要处理的最后一个参数。argv[4] 将为空。

根据您收到的一些答案,这里是关于 execv 和 fork 的讨论

于 2012-09-21T23:21:58.090 回答
0
  1. 你有错误的逻辑。在 execv 之前使用 fork
  2. 将 execv(与 fork 一起)移出循环;
  3. execv 的第一个参数 - 是要执行的二进制文件的路径;2nd - 要传递给二进制文件的参数数组。您在当前目录中拥有名为“Assignments”的子目录并且该目录包含名为“ls”的可执行文件,这是否正确?并且,请仔细阅读“man execv”

更新:

忽略上述第 1 点和第 2 点。

人执行:

   The execv(), execvp(), and execvpe()  functions  provide  an  array  of
   pointers  to  null-terminated  strings that represent the argument list
   available to the new  program.   The  first  argument,  by  convention,
   should  point  to the filename associated with the file being executed.
   The array of pointers must be terminated by a NULL pointer.
于 2012-09-21T23:25:37.727 回答