0

コマンドライン(linux / unixコマンド)からユーザー入力を取得し、プログラム内で実行するプログラムを作成しています。

これまでの私のステップ:

  1. 入力したコマンドの数をユーザーに尋ねる
  2. 子プロセスを作成するためのFork()
  3. 子PIDと親PIDを出力します
  4. ユーザーが各コマンドを入力できるようにし、各入力をargvのインデックスに読み込みます
  5. execvを使用して、argv内で各コマンドを実行します

主な問題は、実行時にexecvコマンドの「bin /ls/」を実行するだけであるということです。

プログラムの実行からの出力例を次に示し

ます。コマンドの数を入力します。2
子のPIDは3487です。親のPIDは3485です
。UNIXコマンドを入力します。lsUNIXコマンドを入力します。-alCMDで「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

コードにある特定の問題の1つは、execの引数としてargv[idx]を渡さなければならないことです。argvを渡すことにより、charポインタの配列を渡します。

また、argcには引数の完全なカウントが含まれ、完全なカウントにはプログラム自体が含まれることにも注意してください。argv [0]には、引数を渡すプログラム名が含まれています。それがforループに反映されているのを見ていません。つまり、独自のプログラムを処理して実行しているということです。

私がこれらを書いた方法は、int idx=0;nullであるargv [idx]ポインターが見つかるまで、int変数(たとえば)を使用して、しばらくの間(または、必要に応じて)argvをトラバースすることです。

たとえば、3つの引数がある場合、argcは4になり、argv[3]が処理する最後の引数になります。argv[4]はnullになります。

あなたが受け取った答えのいくつかに基づいて、ここにexecvとforkの議論があります。

于 2012-09-21T23:21:58.090 に答える
0
  1. あなたは間違った論理を持っています。execvの直前にフォークを使用する
  2. execvを(forkと一緒に)ループの外に移動します。
  3. execvの最初の引数-実行するバイナリファイルへのパスです。2番目-バイナリに渡す引数の配列。これは、現在のディレクトリに「Assignments」という名前のサブディレクトリがあり、このディレクトリに「ls」という名前の実行可能ファイルが含まれているということは正しいですか?そして、「manexecv」を注意深く読んでください

アップデート:

上記のポイント1と2は無視してください。

man execv:

   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 に答える
0

char* argv[20]まず、どちらを定義するmainのは良い考えではありません。20を超える引数を渡すと、配列の境界を超えてしまいます。

scanf("%s", argv[num])次に、私が知る限り、初期化されていないアドレス空間に文字列を読み込もうとしています。

「文字列」のargv[]配列は、プログラムが呼び出されたときにOSによって初期化されます。プログラムに引数を渡さない場合、「文字列」はありません。つまり、ランダムメモリに書き込むことになります。あなたは所有していないかもしれません。

今行っている方法でコマンドを本当にロードしたい場合は、次のことを試してください。

#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 に答える