2

内部および外部コマンドを処理するシェルを作成しようとしています。内部コマンドと外部コマンドを一度に 1 つずつ取得できます。

私の質問は、「ls -l | grep lib | wc -l」のようなコマンドを実行する方法です。

私は fork() を使用しており、char*[] で execv() を介して外部コマンドを渡しています。

これを機能させる方法について何か考えはありますか?pipe() か何かを使用していると思いますが、よくわかりません。

質問の 2 番目の部分: I/O リダイレクトの処理はどうですか? 誰かが役立つ場所を教えてもらえますか?

編集 これまでのところ、@Alex W は私のヒーローです。ただし、pipe() および dup2() コマンドは初めてなので、それぞれの呼び出しと変数が何のためにあるのか少しためらっています。

単一の外部コマンドを処理するコードを次に示します (例 = "ls -l -a"):

    pid_t pid;
    pid = fork();
    if (pid < 0)
    {
        cout << "Fork failed." << endl;
    }
    else if (pid == 0)
    {
        execvp(exec_args[0], exec_args);   //exec_args is a char*[] where 
        _exit (EXIT_FAILURE);              //exec_args[0] contains "/bin/ls"
    }                                          //[1]="ls" and [2]="-l" [3]="-a"
    else
    {
        int status;
        waitpid(pid, &status, 0);
    }
    break;
4

2 に答える 2

2

pipePOSIX システムでは、パイプはファイルと同じように機能します。パイプに書き込み、パイプから読み取ることができますが、パイプに何もない場合はブロックされます。Unix システム コールに関する情報を見つけるのに最適な場所は、システム コールのマニュアル ページです。Unix システムではman pipe、端末に入力します。Unix 端末にアクセスできない場合は、「man pipe」をググってください。man ページの良い点は、特定のシステム コールにどのライブラリを含めるかを示していることです。型システム コールを使用するexecと、まったく新しいプロセスがそのメモリにロードされ、実行していたプロセスが途中で停止することを忘れないでください。

それを使用するには、次のようにします。

int main()
{
    int id[2];
    int fd[2];
    int fd2[2];
    int fd3[2];
    FILE file;
    int status;
    int sz = 0;
    char buff[1000];
    char buff2[1000];
    string launch[2];
    FILE *fp;

    launch[0] = "./anotherProgramToExecute";
    launch[1] = "./yetAnotherProgram";

    pipe(fd);
    pipe(fd2);
    pipe(fd3);

    for(int i = 0; i < 2; i++)
    {
        id[i] = fork();

        if (id[i] == -1) /* an error occurred */
        {
            perror("Fork failed.\n");
        }
        else if (id[i] == 0) /* this is the child process currently acting */
        {
            if(i == 0)
            {
                dup2(fd[1],1);
            }
            else if(i == 1)
            {
                dup2(fd2[0],0);
                dup2(fd3[1],1);
            }
            execlp(launch[i],launch[i], NULL);
        }
        else /* this is the parent process currently acting */
        {
            sz = read(fd[0], buff, 1000);
            buff[sz] = '\0';
            printf("buff = %s\n",buff);

            close(fd[0]);

            write(fd2[1],buff, 1000);

            read(fd3[0],buff2,1000);

            fp = fopen("bin.txt","w");
            if(fp == NULL)
                printf("Cannot open file.\n");
            else
            {
                fprintf(fp,buff2);
                fclose(fp);
            }

            //printf("Creation of Child Process #%d succeeded!\n",id[i]);
            while(waitpid(id[i], &status, WNOHANG) == 0)
                sleep(0.3);
            if (WIFEXITED(status))
            { 
                // successfully terminated children
            }
            else
            {
                perror("Child has not terminated correctly.\n");
            }
        }
    }
}
于 2012-06-03T21:19:46.403 に答える
0

パイプなどに関して私が見た中で最高のオンラインチュートリアルは、古いものですが良いものです: http://beej.us/guide/bgipc/。あなたはそれを閲覧するかもしれません。あなたはそれを気に入ると思う。

于 2012-06-03T21:22:10.397 に答える