migf1 Δημοσ. 2 Ιουνίου 2014 Δημοσ. 2 Ιουνίου 2014 Εννοώ ότι ο geomagas δεν έχει δώσει testcase και παραπονιέται για κάτι που πιστεύει οτί ειναι OS specific. Δεν ξέρω πιο είναι το πρόβλημα αλλά αν υπαρχει standard λύση γιατί να μπλεχτείς με pthreads? Το πρόβλημα του geomagas είναι πως το thread που περιμένει είσοδο από την stdin κάνει suspend ολόκληρο το process όταν το τρέχει ως background job. Αυτό είναι θέμα λειτουργικού και όχι thread library. Παρόλο που έχω να ασχοληθώ με τέτοια πάρα πολύ καιρό, ήμουν 99% σίγουρος πως συμβαίνει έτσι και μόλις τώρα το διασταύρωσα κιόλας: http://stackoverflow.com/questions/17621798/linux-process-in-background-stopped-in-jobs Για αυτό και του πρότεινα να κοιτάξει ως εναλλακτική μήπως τελικά τον εξυπηρετεί καλύτερα να κάνει το project του multi-processing αντί για multi-threading και να δουλέψει με pipes ή με files (π.χ. http://unix.stackexchange.com/questions/83528/pipe-command-output-to-input-of-running-backgrounded-command ). Σκαλίζοντας λίγο περισσότερο σήμερα, βρήκα ένα ωραίο (κατά την άποψή μου) άρθρο που χρησιμοποιεί named pipes για thread communication, με χρήση της select και δουλεύει σε non-blocking mode. Δεν ξέρω όμως αν είναι αυτό που ζητάει ο geomagas και δυστυχώς δεν έχω την υπομονή να το ψάξω περισσότερο αυτήν τη στιγμή. 1
geomagas Δημοσ. 2 Ιουνίου 2014 Μέλος Δημοσ. 2 Ιουνίου 2014 Τα links δεν τα διάβασα ακόμα, θέλω να ηρεμήσω πρώτα, και να τα δω με την ησυχία μου. Πάντως, διασταύρωσα κι εγώ ότι ισχύει αυτό που λες με το μπλοκάρισμα του process. Αλλά το έκανα το πρωί στο γραφείο, και δεν έχω το link. Έκανα κι ένα πείραμα να δω τι παίζει αντίστοιχα με το stdout, και παρατήρησα ότι, ενώ στο linux δεν μασάει, σε FreeBSD γίνεται πάλι suspend: [1] + Suspended (tty output) ./a.out Ωστόσο, έκανα διάφορες δοκιμές, από παραλλαγές του τρόπου του imitheos μέχρι και κάτι τέτοιο, σε συνδυασμό με σημαφόρους, αλλά κάθε μία με οδηγούσε σε διαφορετικό dead end. Τελικά αποφάσισα να τη δώ multi-processing. Για να μην τα πολυλογώ, σε γενικές γραμμές αυτό: pid_t client=fork(); if(client>=0) { if(!client) // Child: create the client, connect and loop { return the_client(args); } else // Parent: Porcess stdin commands { printf("My Offspring: %d\n",client); char in; while((in=mygetch())!='q') printf("You pressed %c\n",in); kill(client,SIGKILL); printf("Exiting...\n"); return 0; } } else { printf("No fork for you!\n"); return 1; } Ενώ λοιπόν όλα δουλεύουν μια χαρά, μόλις πάει το parent στο bg, γίνονται suspend και τα δύο! Επειδή ήμουν σίγουρος ότι θα δούλευε, τι m@l@ki@ έχω κάνει;;;
migf1 Δημοσ. 3 Ιουνίου 2014 Δημοσ. 3 Ιουνίου 2014 Με έκανες και κατέβασα κι έστησα cygwin και στο μηχανάκι με τα XP Για δες, αυτό εδώ σου δουλεύει; #include <stdio.h> #include <unistd.h> #include <sys/stat.h> /* -------------------------------------------------- * * -------------------------------------------------- */ int main( void ) { pid_t pidChild = fork(); if ( pidChild < 0 ) { fprintf( stderr, "fork() failed, bye..."); return 1; } if ( 0 != pidChild ) { puts( "I'm the parent" ); printf( "My child's pid is %d\n", (int)pidChild ); } else { // child process int c = '\0'; puts( "I'm the child" ); printf( "My parent's id is %d\n", (int)getppid() ); puts( "... press q to stop me..." ); setsid() ; // become session leader chdir("/") ; // change the working dir umask(0) ; // clear out the file mode creation mask while( 'q' != (c=getchar()) ) { printf("You pressed %c\n", c); } } return 0; } Αλλά και να σου δουλεύει και στη δική σου πλατφόρμα, το child δουλεύει την stdin παράλληλα με το shell και γίνεται ο χαμός, οπότε τι νόημα έχει; Παρεμπιπτόντως, για να το σταματήσεις πάτα 2-3 φορές q και μετά ENTER. Βασικά το κάνω deamon το child επειδή τερματίζω τον πατέρα αμέσως μετά το fork() και κανονικά με το setsid() έπρεπε να γίνεται detached το controlling tty, και άρα να μη δουλεύει... ίσως είναι ιδιαιτερότητα του cygwin, δεν ξέρω... περισσότερα μπορείς να βρεις εδώ: http://www.win.tue.nl/~aeb/linux/lk/lk-10.html. Γενικώς πάντως, δεν νομίζω ότι γίνεται ένα background process να διαβάζει το tty. Το να κάνει όμως απευθείας poll τα devices είναι διαφορετικό πράγμα (εκείνο το link που λέγαμε με το ioctl() και το linux/input.h. Όταν σου πρότεινα να το κάνεις multi-processed, δεν εννοούσα να στείλεις στο background και τα 2 processes, αλλά να έχεις τον πατέρα στο foreground για να διαβάζει αυτός την stdin και κατόπιν να τη στέλνει στο background process για περαιτέρω επεξεργασία.
geomagas Δημοσ. 3 Ιουνίου 2014 Μέλος Δημοσ. 3 Ιουνίου 2014 Με έκανες και κατέβασα κι έστησα cygwin και στο μηχανάκι με τα XP ...Υπό την απειλή περιστρόφου; Για δες, αυτό εδώ σου δουλεύει; #include <stdio.h> #include <unistd.h> #include <sys/stat.h> /* -------------------------------------------------- * * -------------------------------------------------- */ int main( void ) { pid_t pidChild = fork(); if ( pidChild < 0 ) { fprintf( stderr, "fork() failed, bye..."); return 1; } if ( 0 != pidChild ) { puts( "I'm the parent" ); printf( "My child's pid is %d\n", (int)pidChild ); } else { // child process int c = '\0'; puts( "I'm the child" ); printf( "My parent's id is %d\n", (int)getppid() ); puts( "... press q to stop me..." ); setsid() ; // become session leader chdir("/") ; // change the working dir umask(0) ; // clear out the file mode creation mask while( 'q' != (c=getchar()) ) { printf("You pressed %c\n", c); } } return 0; } Ναι, αυτό δουλεύει όπως το περιγράφεις παρακάτω. Αλλά και να σου δουλεύει και στη δική σου πλατφόρμα, το child δουλεύει την stdin παράλληλα με το shell και γίνεται ο χαμός, οπότε τι νόημα έχει; Παρεμπιπτόντως, για να το σταματήσεις πάτα 2-3 φορές q και μετά ENTER. Βασικά το κάνω deamon το child επειδή τερματίζω τον πατέρα αμέσως μετά το fork() και κανονικά με το setsid() έπρεπε να γίνεται detached το controlling tty, και άρα να μη δουλεύει... ίσως είναι ιδιαιτερότητα του cygwin, δεν ξέρω... περισσότερα μπορείς να βρεις εδώ: http://www.win.tue.nl/~aeb/linux/lk/lk-10.html. Γενικώς πάντως, δεν νομίζω ότι γίνεται ένα background process να διαβάζει το tty. Το να κάνει όμως απευθείας poll τα devices είναι διαφορετικό πράγμα (εκείνο το link που λέγαμε με το ioctl() και το linux/input.h. Όταν σου πρότεινα να το κάνεις multi-processed, δεν εννοούσα να στείλεις στο background και τα 2 processes, αλλά να έχεις τον πατέρα στο foreground για να διαβάζει αυτός την stdin και κατόπιν να τη στέλνει στο background process για περαιτέρω επεξεργασία. Μα γιατί να διαβάζει το background process από το tty; Δεν θέλω αυτό. Επειδή υπάρχει και το ενδεχόμενο να έχω πάρει "λάθος" δρόμο σχεδιαστικά, bare with me να το πω και με άλλα λόγια: Ξέχνα για λίγο το συγκεκριμένο και σκέψου πχ την top. Η top λοιπόν όσο δουλεύει κάνει κάποιο output και δέχεται εντολές από το πληκτρολόγιο. Αυτές οι εντολές είναι σε στυλ keystrokes, με την έννοια ότι δεν χρειάζεται να πατήσεις [q][Enter] για έξοδο, αρκεί να πατήσεις [q]. Ας πούμε τώρα ότι, όσο δουλεύει μπροστά μου η top, εγώ πατάω ^Ζ και bg (πχ για να εκτελέσω ένα ls στο φτερό). Θα μου πει ότι η top είναι πλεον suspended, και πολύ καλά θα κάνει, διότι δεν έχει νόημα ένα bg job να περιμένει input. Όταν όμως τελειώσω τη δουλειά μου και πατήσω πάλι fg, βλέπω πάλι το output της top και μπορώ να της δώσω εντολές από το πληκτρολόγιο, σαν να μη συνέβη τίποτα. Αυτό θέλω να κάνω από την πλευρά του χρήστη. Τώρα, φαντάσου ότι, παράλληλα με τη δουλειά που κάνει η top, θέλει να ανοίξει και κάποιες συνδέσεις σε κάποια services, χρησιμοποιώντας sockets. Αυτές θα τις διαχειρίζεται η top "από πίσω" και δεν θα έχουν καμία σχέση με το ui. Είναι κάποιοι "διάλογοι" με τους servers, που μόνο η top θα ξέρει πως να τους διαχειριστεί. Προφανώς οι διαδικασίες αυτές θα είναι κάποια loops που θα μπλοκάρουν πάνω σε "κάτι", για να αποφύγουμε το hogging. Αυτό ξέρω πως θα το κάνω, βλ. και παραπάνω. Αν λοιπόν η top έκανε τέτοια μαγικά, πως γίνεται όταν τη στέλνω στο bg: - να γίνεται μεν suspend η διαδικασία που περιμένει user input, διότι αυτό είναι το λογικό (μέχρι να ξανάρθει στο fg) - και να μην γίνονται suspend τα threads?/processes?/κάτι-άλλο? που διαχειρίζονται τα active connections;
imitheos Δημοσ. 3 Ιουνίου 2014 Δημοσ. 3 Ιουνίου 2014 Ξέχνα για λίγο το συγκεκριμένο και σκέψου πχ την top. Η top λοιπόν όσο δουλεύει κάνει κάποιο output και δέχεται εντολές από το πληκτρολόγιο. Αυτές οι εντολές είναι σε στυλ keystrokes, με την έννοια ότι δεν χρειάζεται να πατήσεις [q][Enter] για έξοδο, αρκεί να πατήσεις [q]. Ας πούμε τώρα ότι, όσο δουλεύει μπροστά μου η top, εγώ πατάω ^Ζ και bg (πχ για να εκτελέσω ένα ls στο φτερό). Θα μου πει ότι η top είναι πλεον suspended, και πολύ καλά θα κάνει, διότι δεν έχει νόημα ένα bg job να περιμένει input. Όταν όμως τελειώσω τη δουλειά μου και πατήσω πάλι fg, βλέπω πάλι το output της top και μπορώ να της δώσω εντολές από το πληκτρολόγιο, σαν να μη συνέβη τίποτα. Αυτό θέλω να κάνω από την πλευρά του χρήστη. Η διαφορά όμως εδώ είναι ότι η top δεν είναι "background job" αλλά "suspended job". Πάτησες Ctrl-Z και φυσικά η top σταμάτησε. Για να έτρεχε στο παρασκήνιο θα έπρεπε να είχες γράψει και bg μετά το Ctrl-Z. Αν λοιπόν η top έκανε τέτοια μαγικά, πως γίνεται όταν τη στέλνω στο bg: - να γίνεται μεν suspend η διαδικασία που περιμένει user input, διότι αυτό είναι το λογικό (μέχρι να ξανάρθει στο fg) - και να μην γίνονται suspend τα threads?/processes?/κάτι-άλλο? που διαχειρίζονται τα active connections; zsh: suspended (signal) top % bg [2] - continued top [2] + suspended (signal) top Όταν τρέχω bg για να βάλω την top στο background παίρνω ότι γίνεται suspend δηλαδή βλέπω να κάνει αυτό που σου είπα στο πρώτο μου μήνυμα ότι μπορείς να κάνεις, αν και δεν είναι δόκιμο. Να κάνεις δηλαδή trap το signal. Όταν έτρεχα στο παρασκήνιο το μίνι κώδικα που έδωσες έπαιρνα suspended (tty input) όπως είχαμε δει. Ας κάνουμε trap τώρα το signal να δούμε τι θα κάνει. #include <stdio.h> #include <termios.h> #include <unistd.h> #include <signal.h> void mitsos(int sig) { raise(SIGSTOP); } int main(int argc, char *argv[]) { char in; struct sigaction sa; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = mitsos; sigaction(SIGTTIN, &sa, NULL); while((in=getchar())!='q') printf("You pressed %c\n",in); return 0; } % ./a.out ^Z zsh: suspended ./a.out % bg [1] + continued ./a.out [1] + suspended (signal) ./a.out % fg [1] + continued ./a.out You pressed ÿ q % ./a.out & [1] 1733 [1] + suspended (signal) ./a.out Όπως βλέπεις είτε όταν το τρέχω κατευθείαν στο παρασκήνιο ή πατάω Ctrl-Z και το βάζω στο παρασκήνιο παίρνω suspended(signal) αντί για tty input. Η λειτουργία είναι και πάλι η ίδια δηλαδή επειδή χρειάζεται είσοδο, τότε το πρόγραμμα σταματάει και δέχεται το signal TTIN αλλά αυτή τη φορά του έχουμε πει να τρέχει τη δική μας συνάρτηση αντί για αυτή του shell. Σε αυτή τη συνάρτηση μπορείς να βάλεις να γίνεται αυτό που θέλεις (προσοχή στα threads). Εγώ απλά έβαλα να βαράει STOP σήμα οπότε σταματάει όπως η top χωρίς να κάνω housekeeping οπότε μετά παίρνω εκείνο το σκουπίδι πάτησες τάδε. Δοκίμασε το μήπως σου κάνει απλά πρόσεξε το συνδυασμό του με τα νήματα (μήπως αλλάζεις το σήμα αφού σηκωθεί το child ώστε να μην κάνει inherit και αυτό το signal και σταματάει)
migf1 Δημοσ. 3 Ιουνίου 2014 Δημοσ. 3 Ιουνίου 2014 @geomagas: Μου βάζεις δύσκολα, κι όπως σου είπα τα έχω ψιλο-χοντρο-ξεχάσει τα *nix internals, οπότε για να σου απαντήσω πιο λεπτομερώς πρέπει να κάτσω να διαβάζω να τα φρεσκάρω (και τώρα δεν...). Η top όμως κατά πάσα πιθανότητα χρησιμοποιεί curses Επίσης κατά πάσα πιθανότητα πάει και διαβάζει το proc/ virtual file system των processes (πιθανότατα σε timed intervals). Για αρχή δοκίμασε να παίξεις με signal handlers, που σου λέει και ο imitheos, και δοκίμασε όταν κάνεις wake να μπορείς να κάνεις refresh τα data που σε ενδιαφέρει να δείξεις την πρόοδό τους όσο κοιμόσουν (επίσης, δοκίμασε να παίξεις και με pipes για τα in & out streams σου).
geomagas Δημοσ. 3 Ιουνίου 2014 Μέλος Δημοσ. 3 Ιουνίου 2014 @geomagas: Μου βάζεις δύσκολα, κι όπως σου είπα τα έχω ψιλο-χοντρο-ξεχάσει τα *nix internals, οπότε για να σου απαντήσω πιο λεπτομερώς πρέπει να κάτσω να διαβάζω να τα φρεσκάρω (και τώρα δεν...). Χεχε! Δεν ήταν τέτοια η πρόθεσή μου. Είπαμε άλλωστε, το "καψόνι" απευθύνεται στον εαυτό μου, όχι σε άλλους. Οπότε, no sweat! Η διαφορά όμως εδώ είναι ότι η top δεν είναι "background job" αλλά "suspended job". Πάτησες Ctrl-Z και φυσικά η top σταμάτησε. Για να έτρεχε στο παρασκήνιο θα έπρεπε να είχες γράψει και bg μετά το Ctrl-Z. Μα όχι, αφού το είπα ήδη ότι κάνω ^Z και bg. Όπως βλέπεις είτε όταν το τρέχω κατευθείαν στο παρασκήνιο ή πατάω Ctrl-Z και το βάζω στο παρασκήνιο παίρνω suspended(signal) αντί για tty input. Η λειτουργία είναι και πάλι η ίδια δηλαδή επειδή χρειάζεται είσοδο, τότε το πρόγραμμα σταματάει και δέχεται το signal TTIN αλλά αυτή τη φορά του έχουμε πει να τρέχει τη δική μας συνάρτηση αντί για αυτή του shell. Σε αυτή τη συνάρτηση μπορείς να βάλεις να γίνεται αυτό που θέλεις (προσοχή στα threads). Εγώ απλά έβαλα να βαράει STOP σήμα οπότε σταματάει όπως η top χωρίς να κάνω housekeeping οπότε μετά παίρνω εκείνο το σκουπίδι πάτησες τάδε. Δοκίμασε το μήπως σου κάνει απλά πρόσεξε το συνδυασμό του με τα νήματα (μήπως αλλάζεις το σήμα αφού σηκωθεί το child ώστε να μην κάνει inherit και αυτό το signal και σταματάει) Κατανοητός. Να τα πάρουμε τώρα βήμα-βήμα; Έστω ότι εγώ θέλω να τρέχει παράλληλα και αυτό: void *pacer(void *arg) { FILE *f; while(1) { // fopen/fclose every time, for tail -f to work f=fopen("pacer.txt","a"); fprintf(f,"tic-tac\n"); fclose(f); sleep(2); } } Η multi-threaded εκδοχή: int main(int argc, char *argv[]) { char in; struct sigaction sa; pthread_t thread; pthread_create(&thread,NULL,&pacer,NULL); sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = mitsos; sigaction(SIGTTIN, &sa, NULL); while((in=getchar())!='q') printf("You pressed %c\n",in); pthread_cancel(thread); pthread_join(thread,NULL); return 0; } ...και η multi-process: int main(int argc, char *argv[]) { char in; struct sigaction sa; pid_t pidChild = fork(); if ( 0 != pidChild ) { sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = mitsos; sigaction(SIGTTIN, &sa, NULL); while((in=getchar())!='q') printf("You pressed %c\n",in); } else pacer(NULL); // child return 0; } Τρέχοντας οποιοδήποτε από τα δύο σε ένα τερματικό, και σε ένα άλλο αυτό: tail -f pacer.txt βλέπω το αναμενόμενο: Μόλις το βάλω στο background, η tail σταματά να βγάζει γραμμές. Μόλις ξανάρχεται στο fg, η tail συνεχίζει. Καλά το πάω ως εδώ; (Κι εγώ ωστόσο γκουγκλίζω για τα signals, για να δω πως θα βάλω το μήτσο() στο παιχνίδι )
imitheos Δημοσ. 3 Ιουνίου 2014 Δημοσ. 3 Ιουνίου 2014 Μα όχι, αφού το είπα ήδη ότι κάνω ^Z και bg.Όπως πάντα ό,τι να ναι διάβασα Δεν το είδα καν το bg. βλέπω το αναμενόμενο: Μόλις το βάλω στο background, η tail σταματά να βγάζει γραμμές. Μόλις ξανάρχεται στο fg, η tail συνεχίζει. Καλά το πάω ως εδώ; Υποθέτω πως καλά το πας. Το να σταματάει το ένα thread / process οπότε να μην εμφανίζει η tail δεν είναι που ήθελες να κάνεις ? Γενικά οι signal handlers έχουν ένα κάποιο housekeeping που πρέπει να κάνεις για να παίζει το πράγμα σωστά και επίσης δεν μπορείς μέσα τους να τρέξεις ό,τι κώδικα θέλεις αλλά τώρα το TTIN (και το TSTP αν θέλεις να παίζεις και γενικότερα με το Ctrl-Z) δεν είναι και τόσο ιδιαίτερο σήμα οπότε λογικά δεν θα πρηχτείς πολύ. Όσο googlάρεις, όποιο παράδειγμα τρέχει signal και όχι sigaction μακρυά μακρυά.
geomagas Δημοσ. 3 Ιουνίου 2014 Μέλος Δημοσ. 3 Ιουνίου 2014 Το να σταματάει το ένα thread / process οπότε να μην εμφανίζει η tail δεν είναι που ήθελες να κάνεις ? Όχι ακριβώς. Όπως λέω παραπάνω, θέλω να σταματήσει το parent αλλά όχι το child. Αυτός είναι και ο λόγος που γίνεται όλη αυτή η ιστορία. Γενικά οι signal handlers έχουν ένα κάποιο housekeeping που πρέπει να κάνεις για να παίζει το πράγμα σωστά και επίσης δεν μπορείς μέσα τους να τρέξεις ό,τι κώδικα θέλεις αλλά τώρα το TTIN (και το TSTP αν θέλεις να παίζεις και γενικότερα με το Ctrl-Z) δεν είναι και τόσο ιδιαίτερο σήμα οπότε λογικά δεν θα πρηχτείς πολύ. Χμ, ναι, κάπου τα πέτυχα όλα αυτά. Έχει πολύ διάβασμα... Προς το παρόν, βρήκα το SIGCONT και μου άρεσε, οπότε είπα να αντικαταστήσω το raise της mitsos() έτσι: pid_t pidChild; void mitsos(int sig) { kill(pidChild,SIGCONT); } Προφανώς, με σκοπό να δώσω μιά "κλωτσιά" στο child για να συνεχίσει. (Και προφανώς μιλάμε για τη multiprocess εκδοχή) Το αποτέλεσμα είναι ότι... συνεχίζουν και τα δύο!!! Παρόλο που το signal το στέλνω ρητά στο child! Full source: #include <stdio.h> #include <termios.h> #include <unistd.h> #include <signal.h> pid_t pidChild; void mitsos(int sig) { kill(pidChild,SIGCONT); } void *pacer(void *arg) { FILE *f; while(1) { f=fopen("pacer.txt","a"); fprintf(f,"tic-tac\n"); fclose(f); sleep(2); } } int mygetch ( void ) { int ch; struct termios oldt, newt; tcgetattr ( STDIN_FILENO, &oldt ); newt = oldt; newt.c_lflag &= ~( ICANON | ECHO ); tcsetattr ( STDIN_FILENO, TCSANOW, &newt ); ch = getchar(); tcsetattr ( STDIN_FILENO, TCSANOW, &oldt ); return ch; } int main(int argc, char *argv[]) { char in; struct sigaction sa; pidChild = fork(); if ( 0 != pidChild ) { sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = mitsos; sigaction(SIGTTIN, &sa, NULL); while((in=mygetch())!='q') printf("You pressed %c\n",in); } else pacer(NULL); // child return 0; } Σημ: Επανέφερα και τη "δική μου" mygetch() διότι με σκέτη τη getchar() αν το επαναφέρεις στο fg γίνεται ο κακός χαμός στο terminal... Πάμε γι' άλλα λοιπόν. Μόλις έχω νεώτερα, επανέρχομαι Δημήτριος.
imitheos Δημοσ. 3 Ιουνίου 2014 Δημοσ. 3 Ιουνίου 2014 Όχι ακριβώς. Όπως λέω παραπάνω, θέλω να σταματήσει το parent αλλά όχι το child. Αυτός είναι και ο λόγος που γίνεται όλη αυτή η ιστορία. Το αποτέλεσμα είναι ότι... συνεχίζουν και τα δύο!!! Παρόλο που το signal το στέλνω ρητά στο child! Full source: #include <stdio.h> #include <termios.h> #include <unistd.h> #include <signal.h> pid_t pidChild; void mitsos(int sig) { raise(SIGSTOP); } void *pacer(void *arg) { FILE *f; while(1) { f=fopen("pacer.txt","a"); fprintf(f,"tic-tac\n"); fclose(f); sleep(2); } } int mygetch ( void ) { int ch; struct termios oldt, newt; tcgetattr ( STDIN_FILENO, &oldt ); newt = oldt; newt.c_lflag &= ~( ICANON | ECHO ); tcsetattr ( STDIN_FILENO, TCSANOW, &newt ); ch = getchar(); tcsetattr ( STDIN_FILENO, TCSANOW, &oldt ); return ch; } int main(int argc, char *argv[]) { char in; struct sigaction psa; struct sigaction csa; pidChild = fork(); if ( 0 != pidChild ) { sigemptyset(&psa.sa_mask); psa.sa_flags = 0; psa.sa_handler = mitsos; sigaction(SIGTTIN, &psa, NULL); while((in=mygetch())!='q') printf("You pressed %c\n",in); } else { sigemptyset(&csa.sa_mask); csa.sa_flags = 0; csa.sa_handler = SIG_IGN; sigaction(SIGTTIN, &csa, NULL); sigaction(SIGTTOU, &csa, NULL); sigaction(SIGTSTP, &csa, NULL); pacer(NULL); // child } return 0; }Για δες αυτό σου κάνει ? Τα TTIN, TTOU είναι για είσοδο και έξοδο αντίστοιχα ώστε όταν βάλεις το process στο παρασκήνιο είτε πέσεις πάνω στην getchar είτε στο printf και γίνει suspend το parent, να το αγνοήσει το child. Το TSTP είναι για το suspend αυτό καθεαυτό όταν πατήσεις Ctrl-Z να συνεχίσει να τρέχει το pacer και να γράφει στο αρχείο. Αν θέλεις με το Ctrl-Z να σταματάει το child αφαίρεσε αυτή τη γραμμή. Το parent θα μπορούσε να μην έχει καθόλου sigaction αλλά έτσι είναι καλύτερα ώστε να γίνεται το raise και να σταματάει με STOP αντί να γίνονται χαζομάρες. 1
geomagas Δημοσ. 4 Ιουνίου 2014 Μέλος Δημοσ. 4 Ιουνίου 2014 YESSSS! Δουλεύει! BTW, ενδιαφέρουσα η προοπτική με το SIGSTP. Με έβαλες σε σκέψεις! Και το sigaction του parent θα το αφήσω οπωσδήποτε εκεί που είναι, γιατί σίγουρα κάπου θα το χρειαστώ. Βέβαια, έχει ένα θεματάκι: Όταν επιστρέφει στο fg (από bg, όχι από σκέτο ^Z) του λείπει ένα [enter] για να αρχίσει να παίρνει πάλι keystrokes. Αλλά πιθανότατα να αφορά την mygetch(), οπότε θα το ψάξω μόνος μου. @imitheos και @migf1, χρωστάω μπύρες!!! :-D
migf1 Δημοσ. 4 Ιουνίου 2014 Δημοσ. 4 Ιουνίου 2014 YESSSS! Δουλεύει! ... @imitheos και @migf1, χρωστάω μπύρες!!! :-D Αν δεν έρθει κι ο Μήτσος εγώ δεν έρχομαι!
geomagas Δημοσ. 4 Ιουνίου 2014 Μέλος Δημοσ. 4 Ιουνίου 2014 Αν δεν έρθει κι ο Μήτσος εγώ δεν έρχομαι! :lol: Του το είπα και μου απάντησε: "Θα έρθω, αλλά είμαι standby. Άμα πέσει κανένα SIGTTIN θα φύγω νωρίς!"
H_ANARXIA_EINAI_PSEMA Δημοσ. 4 Ιουνίου 2014 Δημοσ. 4 Ιουνίου 2014 Εγώ είχα φανταστεί ότι είναι δουλεία για το sigaction αλλά δεν μίλησα ... Τώρα δεν έχω μπύρα
geomagas Δημοσ. 4 Ιουνίου 2014 Μέλος Δημοσ. 4 Ιουνίου 2014 Ε καλά, αν τύχει και περάσεις (εντελώς τυχαία όμως!) απέξω, θα σε φωνάξουμε. Χίλιοι καλοί χωράνε! 1
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα