2012-10-01 23 views
6

का जवाब नहीं दे रहा है, मैं सी में मूल खोल को कोड कर रहा हूं, और मैं अभी एक बाल प्रक्रिया को निलंबित करने पर काम कर रहा हूं।एसआईजीटीएसटीपी के साथ बाल प्रक्रिया को निलंबित करने के बाद, शेल

मुझे लगता है कि मेरी संकेत हैंडलर सही है, और मेरे बच्चे प्रक्रिया निलंबित किया जाता है, लेकिन उसके बाद, टर्मिनल माता पिता प्रक्रिया पर लौट जाना चाहिए और कहा कि नहीं हो रहा है।

बच्चे को निलंबित कर दिया गया है, लेकिन मेरा खोल अब इनपुट या आउटपुट पंजीकृत नहीं कर रहा है। tcsetpgrp() मदद नहीं कर रहा प्रतीत होता है।

यहाँ SIGTSTP के लिए मेरे खोल कोड में मेरी संकेत हैंडलर है:

void suspend(int sig) { 
    pid_t pid; 
    sigset_t mask; 
    //mpid is the pgid of this shell. 
    tcsetpgrp(STDIN_FILENO, mpid); 
    tcsetpgrp(STDOUT_FILENO, mpid); 
    sigemptyset(&mask); 
    sigaddset(&mask, SIGTSTP); 
    sigprocmask(SIG_UNBLOCK, &mask, NULL); 
    signal(SIGTSTP, SIG_DFL); 
    //active.pid is the pid of the child currently in the fg. 
    if (active.pid != 0) { 
     kill(active.pid, SIGTSTP); 
    } 
    else{ 
     //if this code is being run in the child, child calls SIGTSTP on itself. 
     pid = getpid(); 
     if (pid != 0 && pid != mpid){ 
      kill(pid, SIGTSTP); 
     } 
    } 
    signal(SIGTSTP, suspend); 
} 

किसी को भी मुझे बता सकते हैं मैं गलत क्या कर रहा हूँ?

क्या मैं अपने खोल को बच्चे के साथ निलंबित कर रहा हूं, और क्या मुझे किसी भी तरह से शैल में स्टडीन और स्टडआउट वापस करने की ज़रूरत है? यह मैं कैसे करूंगा?

धन्यवाद!

उत्तर

0

tcsetpgrp निर्दिष्ट करना है कि अग्रभूमि नौकरी क्या है। जब आपका खोल अग्रभूमि में नौकरी पैदा करता है (& के बिना), तो इसे एक नया प्रक्रिया समूह बनाना चाहिए और इसे अग्रभूमि नौकरी (नियंत्रण टर्मिनल का, एसटीडीआईएन पर जो कुछ भी नहीं है) बनाना चाहिए। फिर, CTRL-Z दबाकर, उस नौकरी को टीएसटीपी मिलेगा। यह टर्मिनल है जो नौकरी को निलंबित करता है, न कि आपके खोल। आपका खोल टीएसटीपी को फंसाना नहीं चाहिए या किसी को भी टीएसटीपी नहीं भेजना चाहिए।

यह केवल wait() उस नौकरी के लिए होना चाहिए जो इसे रोक दिया गया है और पता चला है कि यह बंद हो गया है (और अग्रभूमि समूह का दावा करें और नौकरी को आंतरिक रूप से निलंबित कर दें)। आपका fg आदेश काम के अग्रभूमि प्रक्रिया समूह फिर से pgid बनाने के लिए और यह करने के लिए एक SIGCONT भेज सकते हैं और इसे फिर से के लिए प्रतीक्षा है, जबकि bg सिर्फ SIGCONT

+1

उत्तर के लिए धन्यवाद। मैंने जो कहा है, उसे करने की कोशिश की है, लेकिन जब मैं अपना सिग्नल हैंडलर लेता हूं तो टर्मिनल सिर्फ माता-पिता को निलंबित करता है और बैश पर लौटता है। मुझे दौड़ने के लिए माता-पिता की ज़रूरत है। – user1710304

+1

यह सादा गलत है, SIGTSTP को पकड़ने से निश्चित रूप से उसका खोल निलंबित हो जाएगा और बच्चों को प्रक्रियाओं को आगे बढ़ने देगा। उसे पकड़ने की जरूरत है ताकि उसका खोल निलंबित नहीं होगा। मुझे अभी भी एक ही समस्या का सामना करना पड़ रहा है, उसे पहले – Fingolfin

+1

@AdelQodmani का सामना करना पड़ा, टर्मिनल का केवल अग्रभूमि प्रक्रिया समूह एक SIGTSTP प्राप्त करता है जब आप Ctrl-Z दबाते हैं। वह खोल जो सिर्फ प्रक्रिया की समाप्ति की प्रतीक्षा कर रहा है, एक प्रक्रिया समूह में है जो टर्मिनल का अग्रभूमि प्रक्रिया समूह नहीं है। यदि आप चाहें तो _ignore_ SIGTSTP कर सकते हैं, यह संभव है कि अधिकांश गोले क्या करें। मेरा मुद्दा यह था कि आपको टर्मिनल के अग्रभूमि प्रक्रिया समूह के साथ खेलना होगा। –

2

भेजना होगा यह एक पुराने सवाल है, लेकिन अभी भी मुझे लगता है मैं एक जवाब मिल गया लगता होगा।
आप अपने माता-पिता के कोड नहीं लिखा था, लेकिन मैं जैसे अपने दिखता है कुछ संभालने हूँ:

int main(){ 
    pid_t pid = fork(); 
    if(pid == 0){ //child process 
     //call some program 
    else //parent process 
     wait(&status); //or waitpid(pid, &status, 0) 
     //continue with the program 
} 

समस्या इंतजार के साथ है() या waitpid(), ऐसा लगता है अगर आप ओएस पर अपने कार्यक्रम चलाने के लग रहे है उबंटू की तरह का उपयोग कर Ctrl +जेड अपने बच्चे प्रक्रिया SIGTSTP लेकिन प्रतीक्षा हो रही है के बाद() माता-पिता की प्रक्रिया में समारोह अभी भी इंतज़ार कर रहा है!

कि ऐसा करने का सही तरीके से प्रतीक्षा() माता-पिता में ठहराव() के साथ बदलें, और एक अन्य हैंडलर कि SIGCHLD पकड़ने बनाना है। उदाहरण के लिए:

void sigHandler(int signum){ 
    switch(signum){ 
     case SIGCHLD: 
      // note that the last argument is important for the wait to work 
      waitpid(-1, &status, WNOHANG); 
      break; 
    } 
} 

बच्चे की प्रक्रिया के बाद इस मामले में प्राप्त Ctrl +जेड माता पिता की प्रक्रिया भी SIGCHLD और ठहराव() वापसी प्राप्त करते हैं।

0

मुझे यहां प्रश्न का उत्तर देने में देर हो सकती है लेकिन यह वही समस्या है जब मैं एक ही समस्या से फंस गया था।tcsetpgrp के लिए आदमी पृष्ठों()

समारोह tcsetpgrp() के अनुसार के साथ प्रक्रिया समूह आईडी टर्मिनल पर अग्रभूमि प्रक्रिया समूह एफडी जुड़े जिनमें से नियंत्रित टर्मिनल होना चाहिए pgrp प्रक्रिया समूह बनाता है कॉलिंग प्रक्रिया, और अभी भी अपने सत्र से जुड़े हुए हैं। इसके अलावा, pgrp प्रक्रिया को कॉल करने के समान सत्र से संबंधित (nonempty) प्रक्रिया समूह होना चाहिए।

tcsetpgrp() अपने सत्र में एक पृष्ठभूमि प्रक्रिया समूह के एक सदस्य द्वारा कहा जाता है, और फोन करने की प्रक्रिया को अवरुद्ध या SIGTTOU अनदेखी नहीं है, तो एक SIGTTOU संकेत इस पृष्ठभूमि प्रक्रिया समूह के सभी सदस्यों को भेजी जाती है।

तो, मेरे लिए जो काम किया गया वह शेल प्रोग्राम में SIGTTOU सिग्नल को अनदेखा कर रहा था, इससे पहले कि मैंने अग्रभूमि में आने वाली प्रक्रियाएं बनाई हों। अगर मैं इस सिग्नल को अनदेखा नहीं करता हूं, तो कर्नेल इस सिग्नल को मेरे खोल प्रोग्राम में भेज देगा और इसे निलंबित करेगा।