Visualizzazione dei risultati da 1 a 10 su 10
  1. #1
    Utente di HTML.it
    Registrato dal
    Mar 2001
    Messaggi
    117

    [C/C++ - Linux] Exec di linee di comando con pipe "|"

    Salve.
    Ho un piccolo quesito. Ho un semplice programmino C/C++ in Linux che, prendendo come argomenti una linea di comando per la shell la esegue tramite la exec (in particolar modo, io utilizzo la execvp, ma penso che i ragionamenti valgano anche per le altre funzioni della famiglia delle exec). Il mio programmino è il seguente:
    codice:
    #include <stdio.h>
    #include <iostream>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    
    
    using namespace std;
    
    
    int main(int argc, char *argv[])
    {
    	cout << getpid() << ") Sono il processo " << getpid() << endl;
    
    	int pid=vfork();
    	if (pid<0)
    		return -1;
    	else if (pid==0)
    	{
    		execvp(argv[1], argv+1);
    		perror("execvp");
    		return -1;
    	}
    	int status;
    	cout << getpid() << ") Mio figlio ha pid " << pid << endl;
    	wait(&status);
    	cout << getpid() << ") Mio figlio " << pid << " è terminato!" << endl;
    
    	return 0;
    }
    Supponendo che il mio programma compilato si chiamasse ./esegui, se eseguissi ad esempio:
    codice:
    ./esegui ps -aux
    Mi stamperebbe tranquillamente a video tutti i processi in esecuzione nel mio sistema (e similmente farebbe se volessi eseguire altri comandi), ed in più aggiunge le semplici righe di servizio dei miei cout (non cambierebbe assolutamente nulla se anziché i cout del C++ usassi i printf rendendo il programma un programma C puro).

    Tuttavia, se volessi usare un comando con pipe, ad esempio ps -aux | grep "bash", comincerebbero ad esserci problemi. Infatti se faccio:

    codice:
    ./esegui ps -aux | grep "bash"
    Mi stampa sì tutti i processi, ma non le righe di servizio che avevo aggiunto io con i cout, in quanto non comprendono la parola "bash". Infatti il comando viene interpretato come se la prima parte da eseguire fosse ./esegui ps -aux e come se il comando grep dovesse prendere in input tutto l'output di ./esegui ps -aux e non solo quello di ps -aux (non so se mi sono spiegato).

    Non so se ci sono modi per far capire che il comando da passare ad esegui (e quindi alla execvp) è tutto ps -aux | grep "bash". Per ora ho provato a fare così:

    codice:
    #include <stdio.h>
    #include <iostream>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    
    
    using namespace std;
    
    
    int main(int argc, char *argv[])
    {
    	cout << getpid() << ") Sono il processo " << getpid() << endl;
    
    	char* cmd[]={"ps","-aux","|","grep","\"bash\"",(char*)NULL};
    	int pid=vfork();
    	if (pid<0)
    		return -1;
    	else if (pid==0)
    	{
    		execvp("ps", cmd);
    		perror("execvp");
    		return -1;
    	}
    
    	int status;
    	cout << getpid() << ") Mio figlio ha pid " << pid << endl;
    	wait(&status);
    	cout << getpid() << ") Mio figlio " << pid << " è terminato!" << endl;
    
    	return 0;
    }
    Tuttavia, eseguendo ./esegui ottengo addirittura un errore in esecuzione. Non è proprio possibile passare l'operatore pipe "|" ad una funzione di tipo exec? :master:

  2. #2
    Utente di HTML.it
    Registrato dal
    Jul 2010
    Messaggi
    466
    Ciao, devi usare la popen

  3. #3
    Utente di HTML.it
    Registrato dal
    Jul 2010
    Messaggi
    466
    In piu la fork non si chiama così:
    codice:
    	int pid=vfork();
    	if (pid<0)
    		return -1;
    	else if (pid==0)
               ...
    ma cosi
    codice:
       pid_t pid;
       
       if((pid = fork()) == 0)
          /* do your job */
       else
          /*report errors etc */

  4. #4
    Utente di HTML.it
    Registrato dal
    Mar 2001
    Messaggi
    117
    Originariamente inviato da simo_85
    Ciao, devi usare la popen
    Grazie mille!!!! E io che temevo che il giorno prima di ferragosto non avrei trovato nessuno che mi avrebbe risposto. Credo proprio che sia ciò che fa al caso mio. Ora vedo un po' se capisco come funziona e se riesco a fare ciò che volevo.

    Sulla fork non ho ben capito cosa c'è che non va, semmai ti chiedo delucidazioni in pvt per non andare OT.

  5. #5
    Utente di HTML.it
    Registrato dal
    Jul 2010
    Messaggi
    466
    Originariamente inviato da Cell
    Sulla fork non ho ben capito cosa c'è che non va, semmai ti chiedo delucidazioni in pvt per non andare OT.
    É meglio chiamarla e fare le cose come ti ho fatto vedere.. Se crei un solo processo il confronto con lo 0 non ti serve credo, pero se hai un array di processi, ossia ne crei più di 1, fà la differenza nell'esecuzione del programma..

  6. #6
    Utente di HTML.it
    Registrato dal
    Jul 2008
    Messaggi
    1,326
    Queste righe

    codice:
    pid_t pid;
       
       if((pid = fork()) == 0)
          /* do your job */
       else
          /*report errors etc */
    non sono corrette: la fork() ritorna due volte e restituisce 0 nel processo figlio e il pid del processo figlio nel padre. In quel caso, quindi, nel corpo dell'if ci va il codice che deve eseguire il figlio ma nel corpo dell'else non ci può andare la segnalazione di errori, perché altrimenti il processo padre segnalerebbe errori in ogni caso.

    codice:
       pid_t pid;
       
       if((pid = fork()) < 0) {
          /* errore */
       } else if (pid == 0) {
          /* processo figlio */
       } else { /* pid > 0 */
          /* processo padre */
       }
    Aggiungo inoltre che la vfork() è deprecata perché Linux supporta il copy-on-write che di fatto rende inutile i vantaggi offerti in passato dalla vfork().

    EDIT: e ritornando alla questione originaria, se vuoi implementare una pipe prova a leggere qui.
    every day above ground is a good one

  7. #7
    Utente di HTML.it
    Registrato dal
    Jul 2010
    Messaggi
    466
    Originariamente inviato da YuYevon
    codice:
       pid_t pid;
       
       if((pid = fork()) < 0) {
          /* errore */
       } else if (pid == 0) {
          /* processo figlio */
       } else { /* pid > 0 */
          /* processo padre */
       }
    Azz Hai ragione..

  8. #8
    Utente di HTML.it
    Registrato dal
    Mar 2001
    Messaggi
    117
    Originariamente inviato da simo_85
    Azz Hai ragione..
    Era un po' quello che ti avevo fatto notare anche io nel messaggio privato che ti ho scritto, ma forse ero stato meno esplicito nel dirlo.

    Originariamente inviato da simo_85
    Se crei un solo processo il confronto con lo 0 non ti serve credo, pero se hai un array di processi, ossia ne crei più di 1, fà la differenza nell'esecuzione del programma..
    Francamente qui non ho nemmeno capito che intendevi, il confronto con lo 0 serve per capire dove porre le istruzioni che deve eseguire il figlio (del resto, anche tu nel tuo codice facevi il confronto con lo zero).

    Originariamente inviato da YuYevon
    Aggiungo inoltre che la vfork() è deprecata perché Linux supporta il copy-on-write che di fatto rende inutile i vantaggi offerti in passato dalla vfork().

    EDIT: e ritornando alla questione originaria, se vuoi implementare una pipe prova a leggere qui.
    Sulla vfork() sinceramente non sapevo fosse deprecata.
    Ringrazio anche te per il tuo link. Oggi mi sono messo a fare qualche programmino con popen() per capire come funziona anche se ho avuto qualche problemino; ho provato anche la funzione pipe() con un pochino più di fortuna, ma ancora con qualche problemino. Faccio un po' tutte le prove del caso (anche per spratichirmi), poi se ho qualche altro dubbio sulle funzioni per le pipe e su come realizzare quanto chiedevo posto qui (anche se in realtà quello che ponevo era più un esempio, non è che mi serve fare esattamente quello).




    P.S. Comunque il discorso sulle fork() forkiamocelo in privato per non andare troppo OT (anche perché francamente non mi pareva di aver fatto errori ma al più si discuteva di qualche finezza) e lasciamo qui il discorso sulla pipe che è quello che mi serviva.

  9. #9
    Utente di HTML.it
    Registrato dal
    Mar 2001
    Messaggi
    117
    Va bè, comunque più o meno le due funzioni le ho capite abbastanza e ho risolto.
    Ringrazio sia l'immancabile simo_85 che YuYevon per le loro risposte. Thanks!

  10. #10
    Utente di HTML.it
    Registrato dal
    Jul 2010
    Messaggi
    466
    Originariamente inviato da Cell
    Va bè, comunque più o meno le due funzioni le ho capite abbastanza e ho risolto.
    Ringrazio sia l'immancabile simo_85 che YuYevon per le loro risposte. Thanks!
    Figurati, ringrazio anche io YuYevon per la correzzione ed avermi fatto ricordare quel dettaglio..

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.