1. ホーム
  2. c

[解決済み] C言語でプロセスをバックグラウンドに配置する

2022-02-26 18:54:38

質問

現在、以下のような仕事の背景を作成するために飛び込んでいます。 C& . ノンブロッキングの waitpid というのは、これが動作するためには それはわかっています。 また、私はすでに、もし & がコマンドラインの最後に入力されます。 ただ、具体的にどのように終了を伴う処理をバックグラウンドジョブとして送り、また、別のプロンプトが次のコマンドを要求している間に実行するように実装すればいいのかがわかりません。
何でもいいので、よろしくお願いします。

    struct bgprocess{
        int pid;
        struct bgprocess * next;
        struct bgprocess * prev;    
    };

    struct bgprocess * bgprocess1;
    bgprocess1 = malloc(sizeof(struct bgprocess));
    bgprocess1->prev = NULL;
    bgprocess1->next = NULL;
    bgprocess1->pid = NULL;

    struct bgprocess * current;
    current = bgprocess1;

    do{
        int bgreturn = 0;
        while (current != NULL){
            if (waitpid(current->pid, &bgreturn, WNOHANG)){
                printf("Child exited");
                current->prev->next = current->next;
                current->next->prev = current->prev;
                current->prev = NULL;
                current->next = NULL;
                free(current);                  
            }
        current = current->next;    
        }
        if (end){
            int pid = fork();
            if (pid < 0){
                exit(1);            
            }       
            if (pid) {
                execvp(args[0], args);          
                exit(0);            
            }

            struct bgprocess * newNode;
            newNode = malloc(sizeof(struct bgprocess));
            newNode->pid = pid;
            newNode->next = NULL;

            if (current->next == NULL){
                current->next = newNode;        
            }
            while (1){
                if (current->next == NULL){
                    current->next = newNode;
                }           
                current = current->next;
            }

        }
    }
    while (current != NULL);

    int bgreturn = 0;
    while (current != NULL){
        if (waitpid(current->pid, &bgreturn,0)){
            printf("Child exited");
            current->prev->next = current->next;
            current->next->prev = current->prev;
            current->prev = NULL;
            current->next = NULL;
            free(current);  
        }
        current = current->next;
    }
    }

さて、それでもう少し作業してみたのですが、なんとなく分かってきたような気がします。 まだいくつかのシンタックスエラーがあり、それを修正する方法がわからないので、誰かがそれを指摘しない限り、おそらくgdbか何かを使用することになるでしょう。 私は正しい方法でそれを行っていますか、それとも完全に間違っていますか?

どのように解決するのですか?

シェルを実装しているようですね。

を使うだけです。 フォーク を使用して子プロセスを作成します。 そこから exec*ファミリー を使って好きな実行ファイルを実行したり、親が戻ってより多くの情報(次のコマンドなど)を要求している間に子で単にCコードを実行したりすることができます。 待機 をWNOHANGオプションと一緒にループの先頭に置き、 終了した子プロセスをチェックし、最後にもう一度(今回はWNOHANGなしで) 残りの子プロセスをチェックします。

私は、これを実際以上に複雑にしないように勧めなければなりません。 欲しいものを平易な英語(または母国語、擬似コード)で書き出し、それを最小限の工夫でC言語に翻訳するだけです。

(擬似)コードです。

struct child {
    int pid;
    struct child * next;
    struct child * prev;
}
struct child * children = null;
do {
    int return = 0;
    struct child * curr = children;
    while(curr != null){
        if(waitpid(curr->pid, &return, WNOHANG)){
            //Report child exited with return status 'return'
            //Remove child (linked list style)
         }
         curr = curr->next;
     }
     /* PROMPT, ETC */
     if ( doInBackground ){
         int pid = fork();
         if(pid <0 )exit(); //error
         if(pid){
             //Child
             execvp(processName, arrayOfArgs);
             //This should never get executed
             exit();
         }
         //Add pid (linked list style, again)
     }
}while(!exitCondition)

int return = 0;
struct child * curr = children;
while(curr != null){
    if(waitpid(curr->pid, &return, 0)){
        //Report child exited with return status 'return'
        //Remove child (linked list style)
    }
    curr = curr->next;
}