Προς το περιεχόμενο

Πως δουλεύουν τα Pipes σε Linux;


digimyth

Προτεινόμενες αναρτήσεις

Δημοσ.

Χαίρετε

 

Βασικά θα ήθελα να μάθω πως δουλεύουν τα pipes στο linux για να μπορέσω να προγραμματίσω... Το μόνο που θέλω είναι έστω μια πηγή (βιβλίο, σελίδα, κτλ...) που να μπορώ να μάθω. Και ένα παράδειγμα χρήσης pipes σε C θα ήταν ευπρόσδεκτο.:-)

 

Thanks!

Δημοσ.

Η σύνδεση που δώσατε είναι για pipes στο κέλυφος και όχι για προγραμμάτισμο. Πάντως η έννοια του pipe είναι η ίδια και στις δύο περιπτώσεις: δημιουργία ενός διαύλου (pipe) ενδοεπικοινωνίας μεταξύ δυο εφαρμογών. Στην C γίνεται με την popen:

 

>
#include <stdio.h>

int main(void)
{
 FILE * pipe_stream;
 char buf[512];

 if ( ( pipe_strean = popen ("/usr/bin/ls", "r")) == NULL) /* open pipe with program 'ls' */
 {
   fprintf (stderr, "popen error!\n");
 }
 else
 {
   while (fgets(buf, 512, pipe_stream) != NULL) /* read pipe (output of program 'ls') */
     fprintf(stdout,"%s", buf);

   pclose (pipe_stream);
 }
 return (0);
}

 

ΣΗΜΕΙΩΣΗ: Ο κώδικας δεν είμαι σίγουρος αν κάνει compile, γιατι δεν έχω έυκαιρο μηχάνημα με linux.

 

Για περισσότερες πληροφορίες ψάξε για την popen.

Δημοσ.

Βρήκα αυτό:

 

 

>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
    
/* Read characters from the pipe and echo them to stdout. */
    
void read_from_pipe (int file)
{
 FILE *stream;
 int c;
 stream = fdopen (file, "r");
 while ((c = fgetc (stream)) != EOF)
   putchar (c);
 fclose (stream);
}
  
/* Write some random text to the pipe. */
    
void write_to_pipe (int file)
{
 FILE *stream;
 stream = fdopen (file, "w");
 fprintf (stream, "hello, world!\n");
 fprintf (stream, "goodbye, world!\n");
 fclose (stream);
}
    
int main (void)
{
 pid_t pid;
 int mypipe[2];
  
 /* Create the pipe. */
 if (pipe (mypipe))
 {
   fprintf (stderr, "Pipe failed.\n");
   return EXIT_FAILURE;
 }
    
 /* Create the child process. */
 pid = fork ();
 if (pid == (pid_t) 0)
 {
   /* This is the child process. Close other end first. */
   close (mypipe[1]);
   read_from_pipe (mypipe[0]);
   return EXIT_SUCCESS;
 }
 else if (pid < (pid_t) 0)
      {
        /* The fork failed. */
        fprintf (stderr, "Fork failed.\n");
        return EXIT_FAILURE;
      }
      else
      {
        /* This is the parent process. Close other end first. */
        close (mypipe[0]);
        write_to_pipe (mypipe[1]);
        return EXIT_SUCCESS;
      }
 }

 

 

Αν και αδυνατώ να κατανοήσω πως όταν γράφεις στο mypipe[1] μετά το διαβάζεις από το mypipe[0] αλλά και για ποιο λόγο πρέπει να το κλείσεις!

Δημοσ.

Στο παράδειγμα που παρέθεσες χρησιμοποιείται η εντολή pipe η οποία στην ουσία δημιούργει δύο "αρχεία" (file descriptors) δυναμικά, στα οποία έχει πρόσβαση μόνο αυτός που την κάλεσε, και χρησιμοιποιείται για την ενδο-επικοινωνία μέσα στήν ίδια την εφαρμογή. Πιο συγκεκριμένα τα δεδομένα που γράφονται στον file descriptor mypipe[1] διαβάζονται από τον file descriptor mypipe[0].

 

Το παράδειγμα για να σου αποδείξει την χρησιμότητα της εντολής αυτής δημιουργεί μία επιπλέον διεργασία-παιδί (child process) με την εντολή fork, και χρησιμοποιεί την pipe για επικοινωνία μεταξύ διεργασία-πατέρα (parent process) και διεργασία-παιδί (child process). Μετά την fork η κάθε διεργασία κλείνει το άκρο της επικοινωνίας που δεν χρησιμοποιεί.

Δημοσ.

Γεια,

Εγώ έχω μία άλλη απορία: Θέλω να κοιτάζω σε ένα pipe αρχείο αν υπάρχει κάτι γραμμένο μέσα. Αν υπάρχει να το διαβάζω, ενώ αν δεν υπάρχει να προχωράω παρακάτω στο πρόγραμμά μου και να μην περιμένω.

Από ότι έχω καταλάβει μέχρι τώρα, πρέπει να χρησιμοποιήσω την open και να βάλω flag O_NONBLOCK. Μετά κάνω read, αλλά φαίνεται σαν να μη διαβάζει τίποτα και μάλιστα η read μου επιστρέφει τιμή 0...:cry:

Την είσοδο στο pipe την παιρνάω από ένα shell με την εντολή

echo mplampla >> pipefile

Καμία βοήθεια κανείς?

Ευχαριστώ!

Δημοσ.
Γεια,

Εγώ έχω μία άλλη απορία: Θέλω να κοιτάζω σε ένα pipe αρχείο αν υπάρχει κάτι γραμμένο μέσα. Αν υπάρχει να το διαβάζω, ενώ αν δεν υπάρχει να προχωράω παρακάτω στο πρόγραμμά μου και να μην περιμένω.

Από ότι έχω καταλάβει μέχρι τώρα, πρέπει να χρησιμοποιήσω την open και να βάλω flag O_NONBLOCK. Μετά κάνω read, αλλά φαίνεται σαν να μη διαβάζει τίποτα και μάλιστα η read μου επιστρέφει τιμή 0...:cry:

Την είσοδο στο pipe την παιρνάω από ένα shell με την εντολή

echo mplampla << pipefile

Καμία βοήθεια κανείς?

Ευχαριστώ!

 

θα πρέπει να χρησιμοποιήσεις συναρτήσεις όπως η select/poll/epoll κτλ. για να κάνεις poll όλα τα file descriptors.

 

Ρίξε μια ματιά στο παρακάτω link, μπορεί να σε βοηθήσει

http://www.lowtek.com/sockets/select.html

Δημοσ.
θα πρέπει να χρησιμοποιήσεις συναρτήσεις όπως η select/poll/epoll κτλ. για να κάνεις poll όλα τα file descriptors.

 

Ρίξε μια ματιά στο παρακάτω link, μπορεί να σε βοηθήσει

http://www.lowtek.com/sockets/select.html

Κάτσε, επειδή τα Αγγλικά μου δεν είναι και τόσο καλά και επειδή ούτε που την έχω ξαναακούσει αυτήν την poll, αν δε σου κάνει κόπο, μπορείς να μου εξηγήσεις τι κάνει αυτή η poll, για να καταλάβω τι με συμβουλεύεις να κάνω?

 

Επίσης, τρόπος να διαβάσω ΑΠΛΑ από το pipe δεν υπάρχει?

Ο κώδικάς μου είναι αυτός:

>
 char *filename = //filepath tou pipe;
 int istream;
 ssize_t readcnt;
 char buffer[1];

 sleep(4); //koimatai gia na prolabw na kanw echo sto pipefile

 istream = open (filename, O_RDONLY | O_NONBLOCK, "r");
 readcnt = read(istream, buffer, (size_t)1);
 if (readcnt == -1) {
   printf("Error opening input pipe %s\n", filename);
 } else if( readcnt == 0 ) {
   printf( "to readcns itan 0\n" );
 } else {
   printf( "diabasa: %s\n", buffer );
 }

Δημοσ.

@eirinikp: έχεις ένα μικρό λάθος στον κώδικα σου:

>
 istream = open (filename, O_RDONLY | O_NONBLOCK, "r");
 readcnt = read(istream, buffer, (size_t)1);
 if (readcnt == -1) {
   printf("Error opening input pipe %s\n", filename);
 } else if( readcnt == 0 ) {
   printf( "to readcns itan 0\n" );
 } else {
   printf( "diabasa: %s\n", buffer );
 }

 

θα πρέπει να είναι:

>
 istream = open (filename, O_RDONLY | O_NONBLOCK, "r");
 [color="Red"]if (istream == -1) {
   printf("Error opening input pipe %s\n", filename);
 } else 
 {
   readcnt = read(istream, buffer, (size_t)1);
   if (readcnt == -1) {
     printf("Error reading input pipe %s\n", filename);
   } else if( readcnt == 0 ) {
     printf( "to readcns itan 0\n" );
   } else {
     printf( "diabasa: %s\n", buffer );
 }[/color]

 

Αυτό που θέλεις να κάνεις στην ουσία δεν είναι να διαβάσεις ένα pipe, αλλά (echo mplampla << pipefile) να διαβάσεις από το stdin γιατί το "<<" δηλώνει ανακατεύθυνση των περιεχoμένων του αρχείου pipefile στο προγραμμα echo. Ένα pipe είναι το παρακάτω: "ls | sort".

Δημοσ.

>
 istream = open (filename, O_RDONLY | O_NONBLOCK, "r");
 [color="Red"]if (istream == -1) {
   printf("Error opening input pipe %s\n", filename);
 }[/color]

Ευχαριστώ για τη διόρθωση αλλά το είχα υπόψην μου στο συνολικό πρόγραμμα, γιατί αμέσως πριν το ανοίξω είχα κάνει έλεγχο αν υπάρχει. Δεν έχει σημασία.

Πάντως γενικά χθες δούλεψε οπότε όλα καλά!

Ευχαριστώ και πάλι!

Αρχειοθετημένο

Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.

  • Δημιουργία νέου...