1

ユーザーがコマンドの後に - を付けると、バックグラウンドで実行されるようにしたい。何らかの理由で、コマンドを正常に実行すると待機し、バックグラウンドでコマンドを実行すると機能しますが、コマンドを正常に実行すると待機しません。私はちょっとした間違ったことをしているだけだと確信しています。何か案は:

void executeSystemCommand(char *strippedCommand, char *background, int argc, char **args) {
    char pathToExecute[80];


    // Check if command will be executed in the background
    int shellArgs;
    bool bg; 
    if (!strcmp(background, "-")) {
        bg = true;
        shellArgs = argc -1; 
    } else {
        bg = false;
        shellArgs = argc;
    }   

    // Save the linux commands in a new array
    char *executableCommands[shellArgs+1];
    int j;
    for (j = 0; j < shellArgs+1; j++) {
        executableCommands[j] = args[j];
    }   
    executableCommands[shellArgs] = NULL;

    // Check the $PATH
    const char delimiters[] = ":";
    char *token, *cp;
    char *forLater;
    int count = 0;
    char *path;
    path = getenv("PATH");

    // All of this just breaks up the path into separate strings
    cp = strdup(path);    
    forLater = strdup(path);
    token = strtok (cp, delimiters); 
    while ((token = strtok (NULL, delimiters)) != NULL) {
        count++;
    }   
    char **argv;
    int size = count+1;
    argv = (char**) malloc (size);
    count = 0;
    token = strtok (forLater, delimiters); 
    argv[0] = (char*) malloc (50);
    argv[0] = token;
    strcpy(argv[0],token);
    while ((token = strtok (NULL, delimiters)) != NULL) {
        count++;
        argv[count] = (char*) malloc (50);
        argv[count] = token;
    }   

    // This goes through the path to see if the linux command they entered
    // Ex: sleep exists in one of those files and saves it to a var
    int i;
    bool weHaveIt = false;
    int ac; 
    for (i = 0; i < count; i++) {
        char str[80];
        strcpy(str, argv[i]);
        strcat(str, "/");
        strcat(str, args[0]);
        ac = access(str, F_OK);
        if (ac == 0) {
            weHaveIt = true;
            strcpy(pathToExecute, str);
            break;
        }
    }

    if (!weHaveIt) {
        printf("That is not a valid command. SORRY!\n");
        return;
    }

    executableCommands[0] = pathToExecute;
    int status;

    // Get the array for 

    // If user wants command to be a background process
    if (bg) {
        int background_process_id;
        pid_t fork_return;
        fork_return = fork();

        if (fork_return == 0) {
            background_process_id = getpid();
            addJobToTable(strippedCommand, background_process_id);
            setpgid(0, 0);
            execve(executableCommands[0], executableCommands, NULL);
            exit(0);
        } else {
            return;
        }
    } else {
        int background_process_id;
        pid_t fork_return;
        fork_return = fork();

        if (fork_return == 0) {
            background_process_id = getpid();
            status = execve(executableCommands[0], executableCommands, NULL);
            exit(0);
        } else {
                wait(&status);
                return;
        }
    }
}
4

2 に答える 2

5

wait2 番目のジョブが終了し、処理されるのを待っているため、3 番目のジョブの madeの呼び出しはすぐに返されます (「ゾンビ」とも呼ばれます)。終了したプロセスの PID であるの戻り値をwait(&status)確認し、それが待っていたプロセスであることを確認できます。waitそうでない場合は、もう一度電話してください。

waitpidまたは、特定のプロセスを待機する を使用します。

/* Wait for child. was: wait(&status) */
waitpid(fork_return, &status, 0); 

これを行う場合はSIGCHLD、「ゾンビ」子プロセスの蓄積を防ぐために、終了したバックグラウンド ジョブを処理するためのシグナル ハンドラを実装する必要があります。

それに加えて、バックグラウンド ジョブの場合、fork()0 を返すブランチは既に新しいプロセスにいるためaddJobToTable、間違ったプロセスで呼び出しが行われます。また、すべての呼び出しの戻り値を確認する必要があります。そうしないと、何かが失敗していて、それがわからない可能性があります。したがって、バックグラウンドでジョブを実行するためのコードは、次のようになります。

    if (fork_return == 0) {
        setpgid(0, 0);
        if (execve(executableCommands[0], executableCommands, NULL) == -1) {
            perror("execve");
            exit(1);
        }
    } else if (fork_return != -1) {
        addJobToTable(strippedCommand, fork_return);
        return;
    } else {
        perror("fork"); /* fork failed */
        return;
    }
于 2012-10-17T07:18:18.367 に答える
1

で作成されたすべての子プロセスfork()は、親プロセスが終了すると終了します。

if (fork_return == 0) {
   /* child process, do stuff */
} else {
   /* parent process, exit immediately */
   return;
}

説明

fork現在のプロセス (親) の子プロセスとして新しいプロセスを生成します。Unix ライクなオペレーティング システムでプロセスが終了すると、そのすべての子プロセスも終了します。独自の子プロセスがある場合、これらも終了します。

解決

&ほとんどのシェルでは、行末にアンパサンドを追加すると、バックグラウンドでプロセスを開始できます。

myApplication arg1 arg2 arg3 ... argN &
于 2012-10-17T05:39:14.313 に答える