मैंने सी में लिनक्स खोल की तरह एक बैश लिखा है।

(मेरे भंडार का लिंक:https://github.com/oneiro-naut/wish .फ़ाइल src/execute.c में execute_pipeline फ़ंक्शन है)

मुझे कुछ आउटपुट उत्पन्न करने वाले बिल्टिन कमांड को लागू करने में समस्या हो रही है। बिल्टिन जो cd और exit जैसे कोई आउटपुट नहीं देते ठीक काम करते हैं। बाहरी आदेश सुचारू रूप से चलते हैं। शेल में पाइप निर्माण और I/O पुनर्निर्देशन के लिए भी समर्थन है। समस्या तब होती है जब मैं एक आंतरिक कमांड चलाने की कोशिश करता हूं (जो सिर्फ एक संदेश प्रिंट कर रहा है)। जब मैं एक पाइप का उपयोग करके बिल्ट कमांड के आउटपुट को grep कमांड पर रीडायरेक्ट करता हूं तो grep चाइल्ड प्रोसेस हैंग हो जाता है जो मुझे लगता है कि हो रहा है क्योंकि पाइप से पढ़ते समय grep स्ट्रीम (या EOF) के अंत का कभी सामना नहीं करता है।

नोट: ऐसा तब नहीं होता है जब पाइपलाइन में केवल बाहरी कमांड होते हैं। (मैंने ध्यान रखा है कि कोई (बाहरी) कमांड खत्म होने से पहले अगला कमांड अभी तक शुरू नहीं हुआ है इसलिए यह वहां लटका नहीं है)

यहाँ मेरी समस्या का एक सरलीकृत संस्करण है `

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

int main()
{

int pipe_fd[2] = {-1,-1};
int EXIT_STAT = 0;

pipe(pipe_fd);//creating pipe


char* argv[]={"grep","Radiohead",NULL};

int std_out_dup = dup(1);
dup2(pipe_fd[1],1); // redirecting stdout to parent pipe's read end
//close(pipe_fd[0]);//closing parent pipe's write end 

printf("Alice in Chains\n");
printf("Radiohead\n");
printf("Dinosaur Jr.\n");
printf("Pixies\n");
printf("Soundgarden\n");
printf("Porcupine Tree\n");
printf("Pain of Salvation\n");


pid_t pid = fork();
if(pid == 0)//child process
{
dup2(pipe_fd[0],0); //redirecting grep's stdin to parent pipe's write end
close(pipe_fd[1]);
execvp(argv[0],argv);//executing grep command
perror("\n");
exit(-1);
}


else if(pid > 0)//parent process
{

    int i;//closing pipes for parent
    for(i=0;i<2;i++)
        close(pipe_fd[i]);

    do{ // waiting for grep to exit
        waitpid(pid,&EXIT_STAT,WUNTRACED);
        //write(,"\x4",1);
    }while(!WIFEXITED(EXIT_STAT)&&!WIFSIGNALED(EXIT_STAT));
}
else ;//fork error

dup2(std_out_dup,1); // restore stdout fd for parent process



return 0;

}

`
अगर मैं इसे बिना कुछ प्रिंट किए चलाने की कोशिश करता हूं तो प्रोग्राम हैंग हो जाता है। लेकिन ^D दबाने से आउटपुट उत्पन्न करने वाला प्रोग्राम समाप्त हो जाता है:

Alice in Chains Radiohead Dinosaur Jr. Pixies Soundgarden Porcupine Tree Pain of Salvation

तो ऐसा लगता है कि grep अनिश्चित काल तक पढ़ने में सक्षम नहीं है क्योंकि इसे कोई EOF सिग्नल नहीं मिल रहा है। कृपया मेरी गलतियों को इंगित करें मैं वास्तव में भ्रमित हूं।

संपादित करें: अब ^D दबाने से भी समाप्त नहीं होता है, इसलिए मुझे प्रोग्राम को केवल ^C करना होगा।

सुधार के बाद कार्यक्रम:

int main()
{

    int pipe_fd[2] = {-1,-1};
    int EXIT_STAT = 0;

    pipe(pipe_fd);//creating pipe


    char* argv[]={"grep","Radiohead",NULL};

    int std_out_dup = dup(1);
    //printf("%d \n",std_out_dup);
    dup2(pipe_fd[1],1); // redirecting stdout to parent pipe's read end
    //close(pipe_fd[0]);//closing parent pipe's write end 

    printf("Alice in Chains\n");
    printf("Radiohead\n");
    printf("Dinosaur Jr.\n");
    printf("Pixies\n");
    printf("Soundgarden\n");
    printf("Porcupine Tree\n");
    printf("Pain of Salvation\n");
    fflush(stdout);

    pid_t pid = fork();
    if(pid == 0)//child process
    {
    close(pipe_fd[1]);
    dup2(pipe_fd[0],0); //redirecting grep's stdin to parent pipe's write end
    dup2(std_out_dup,1); // restore stdout fd for parent process
    execvp(argv[0],argv);//executing grep command
    perror("\n");
    exit(-1);
    }


    else if(pid > 0)//parent process
    {

        int i;//closing pipes for parent

        for(i=0;i<2;i++)
           close(pipe_fd[i]);

        dup2(std_out_dup,1); // restore stdout fd for parent process

        do{ // waiting for grep to exit
            waitpid(pid,&EXIT_STAT,WUNTRACED);
        }while(!WIFEXITED(EXIT_STAT)&&!WIFSIGNALED(EXIT_STAT));
      }
          else ;//fork error



       return 0;
    }
2
oneironaut 22 जिंदा 2020, 21:39

1 उत्तर

सबसे बढ़िया उत्तर

तुम्हे करना चाहिए

1. बच्चे में स्टडआउट बहाल करें; अन्यथा grep चाइल्ड प्रोसेस पाइप के राइट एंड पर लिखेगी जो कि उसका स्टड है।

if(pid == 0)//child process ... { के ठीक बाद एक dup2(std_out_dup,1) जोड़ें

2. उन सभी .... printf("Pain of Salvation\n"); प्रिंटफ़ के बाद एक fflush(stdout) जोड़ें; अन्यथा धारा दो बार प्रवाहित हो जाएगी।

3. माता-पिता और बच्चे दोनों में पाइप के सभी लेखन सिरों को बंद करें; पैरेंट में wait लूप से पहले या तो dup2(std_out_dup,1) या close(1) जोड़ें।

1
mosvy 22 जिंदा 2020, 23:23