|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Member
Iscritto dal: Feb 2005
Messaggi: 40
|
[C linux] fork in nuova console
Salve a tutti
ho il seguente rompicapo. Ho fatto un programmino semplice per imparare le fork ma vorrei far in modo che il processo figlio venga eseguito in un nuovo terminale. Attenzione il processo padre e figlio non sono eseguiti in maniera concorrenziale; il padre attende la fine dell'esecuzione del figlio. Ho provato a girare su internet e diverse soluzioni non mi hanno portato a nulla. Ad esempio nel codice filgio ho eseguito un system("gnome-terminal"); che mi apre solo un nuovo terminale mentre il mio intento e' quello di eseguire il processo filgio nel nuovo terminale (basta anche solamente una banale printf). Qualche ideia. Grazie a tuti |
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: Aug 2001
Città: San Francisco, CA, USA
Messaggi: 13827
|
Mmm beh, quello che vuoi fare è anomalo. Purtroppo non credo ci sia un modo semplicissimo per farlo.
Comunque l'output di un terminale in genere è collegato a un file su disco , scrivendo su quel file scrivi nel terminale. Puoi sapere qual'è il file collegato ad un certo terminale usando il comando "tty" Codice:
[hades@artemis ~]$ tty /dev/pts/1 [hades@artemis ~]$ Codice:
[hades@artemis ~]$ echo "ciao" > /dev/pts/1 ciao [hades@artemis ~]$ Rimane il problema di come sapere il nome del file collegato al terminale aperto dal programma . O ce lo infili fisso dentro nel programma (ma visto che cambia a seconda del terminale non è una buona idea) o lo ottieni dinamicamente dal programma , ma è un po' più complicato (dovresti forkare, ridirezionare lo standard output del figlio in una pipe collegata al padre, fare execv sul programma "/usr/bin/tty" e la stringa che arriva dall'altro capo della pipe dovrebbe essere il file in questione). Forse visto che sei all'inizio ti conviene comunque infilarlo direttamente dentro nel programma In ordine quello che dovresti fare è: - forkare il programma e nel figlio fare "execv()" di gnome-terminal per aprire un nuovo terminale. - nel padre del precedente fork apri il file relativo al nuovo terminale aperto (se hai solo due terminali aperti nel server X in genere uno è /dev/pts/1 e l'altro è /dev/pts/2 quindi il file da aprire dovrebbe essere /dev/pts/2 ). - forki di nuovo il programma e nel figlio duplichi il file descriptor del nuovo terminale sostituendo il file descriptor dello standard output (puoi farlo con "dup2( new_terminal_fid, 1);" dove new_terminal_fid è la variabile che contiene il file descriptor aperto del file /dev/pts/2 ottenuto dalla "open()" ) - a questo punto nel figlio se chiami "printf()" dovrebbe scrivere nel nuovo terminale. Ciao
__________________
GPU Compiler Engineer Ultima modifica di AnonimoVeneziano : 30-08-2011 alle 22:19. |
|
|
|
|
|
#3 |
|
Member
Iscritto dal: Feb 2005
Messaggi: 40
|
Grazie per la risposta
Domani a mente lucida riflettero' su quello che hai detto. A grandi linee ho capito devo "solo" trasformarlo in codice. Grazie ancora |
|
|
|
|
|
#4 | |
|
Member
Iscritto dal: Feb 2005
Messaggi: 40
|
Quote:
|
|
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Dec 2005
Città: Istanbul
Messaggi: 1817
|
Il file descriptor della console di gnome-terminal non va bene, perche' e' la stessa del padre (e' l'output del programma gnome-terminal, non dei programmi che quest'ultimo fa girare).
Vedo due alternative semplici, che coinvolgono l'esecuzione di un piccolo script da parte di gnome-terminal (io usero' piu' sotto xterm, ma non cambia tanto la cosa). La prima e' quella di far partire il terminale e fargli eseguire il comando "tty", salvarlo su un file in /tmp e poi mettersi in attesa. L'altro processo aprira' il file specificato, legge il nome della console, apre il device relativo e lo imposta come stdout. Alternativa due: si salta il passaggio di scrivere da qualche parte il nome del terminale, si crea una fifo che viene impostata da una parte come output e dall'altra come input. Impostare l'input di gnome-terminal non e' altro che chiamare uno script che fa il cat della fifo Sono abbastanza simili, ma mi piace di piu' la seconda fondamentalmente per il fatto che in questo modo il terminale si chiude automaticamente quando il processo scrivende finisce, mentre nell'altro caso devo fare una kill del processo relativo. Questo e' un esempio di come puo' funzionare: fa partire una shell che scrive sulla seconda finestra. Sostituisci i programmi indicati con quelli che usi tu Codice:
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
char fifo_name[128];
int fifo_fd;
void display_proc()
{
char cmd[128];
snprintf(cmd,128,"/usr/local/bin/xterm -e \"cat %s\"",fifo_name);
system(cmd);
}
void worker_proc()
{
char cmd[128];
freopen(fifo_name, "w+", stdout);
system("/usr/local/bin/bash");
}
int main()
{
int i,j;
snprintf(fifo_name,128,"/tmp/tmpXXXX");
mktemp(fifo_name);
printf("Fifo name: %s\n", fifo_name);
fifo_fd = mkfifo(fifo_name,0700);
switch( fork())
{
case 0:
display_proc();
return;
case -1:
printf("Error while forking: %s\n", strerror(errno));
return;
default:
break;
}
worker_proc();
}
__________________
One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. —Guy Steele |
|
|
|
|
|
#6 | |
|
Senior Member
Iscritto dal: Aug 2001
Città: San Francisco, CA, USA
Messaggi: 13827
|
Quote:
non so cosa HO bevuto quella sera, ma è ovvio che era qualcosa di forte perchè è naturale che ritorni quella del padre visto che il processo figlio è collegato a quel terminale.Consiglio cannato
__________________
GPU Compiler Engineer Ultima modifica di AnonimoVeneziano : 04-09-2011 alle 11:36. |
|
|
|
|
|
|
#7 | |
|
Senior Member
Iscritto dal: Aug 2001
Città: San Francisco, CA, USA
Messaggi: 13827
|
Quote:
snprintf(fifo_name,128,"/tmp/tmpXXXX"); dovrebbe essere snprintf(fifo_name,128,"/tmp/tmpXXXXXX"); in quanto mktemp vuole almeno 6 X come minimo (almeno per la mia versione delle glibc) Comunque mktemp dovrebbe essere deprecata, quindi se magari si potesse trovare un modo di non usarla sarebbe meglio (tanto per evitare un warning).
__________________
GPU Compiler Engineer |
|
|
|
|
|
|
#8 | |||
|
Member
Iscritto dal: Feb 2005
Messaggi: 40
|
Quote:
Quote:
Quote:
Posso usare una pipe invece di una fifo? Aprendo un terminale nuovo con system(....) c'e' rapporto di parentela tra il mio processo ed il nuovo terminale? Grazie |
|||
|
|
|
|
|
#9 |
|
Senior Member
Iscritto dal: Feb 2006
Messaggi: 1304
|
Non basta lanciare un terminal figlio che esegue un processo predefinito, e poi termina insieme a questo?
Il processo padre del secondo terminal così saprebbe perfettamente quando il task è finito! Altrimenti, si possono fare due processi non padre/figlio che condividono una pipe... ma allora le possibilità sono infinite dato che è un generico problema di IPC. |
|
|
|
|
|
#10 | |
|
Senior Member
Iscritto dal: Aug 2001
Città: San Francisco, CA, USA
Messaggi: 13827
|
Quote:
Per una soluzione senza fifo ho modificato la versione di marco tirando fuori una roba del genere : Codice:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <pty.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
char name[100];
void display_proc()
{
system("/usr/bin/xterm");
}
void worker_proc()
{
char cmd[128];
int fd;
while ((fd = open(name, O_WRONLY)) == -1);
fd = dup2(fd, 1);
execl("/bin/bash", "/bin/bash", NULL);
}
int main()
{
int i,j, pid;
openpty(&i, &j, name, NULL, NULL);
close(i);
close(j);
printf("%s\n", name);
switch( pid = fork())
{
case 0:
display_proc();
return 0;
case -1:
printf("Error while forking: %s\n", strerror(errno));
return 1;
default:
break;
}
worker_proc();
return 0;
}
Se venisse aperto un terminale da un altra parte tra la chiamata a "openpty" e l'apertura di xterm potrebbe non funzionare (è comunque una cosa quasi impossibile visto che accade tutto molto velocemente). La stessa cosa potrebbe succedere con la fifo se un programma tra la chiamata a mktemp e mkfifo creasse una fifo con lo stesso nome. Ciao
__________________
GPU Compiler Engineer |
|
|
|
|
|
|
#11 | |
|
Senior Member
Iscritto dal: Aug 2001
Città: San Francisco, CA, USA
Messaggi: 13827
|
Quote:
Tecnicamente si potrebbe scrivere un altro programma server che ad esempio usa i socket o un altro sistema di IPC che viene lanciato sul terminale "figlio" e rimane in ascolto di dati da visualizzare da parte di un processo padre. Il padre gli spedirebbe i dati da visualizzare e lui li printerebbe sul terminale aperto. In tutti i casi sono soluzioni non semplicissime
__________________
GPU Compiler Engineer |
|
|
|
|
|
|
#12 | ||
|
Senior Member
Iscritto dal: Dec 2005
Città: Istanbul
Messaggi: 1817
|
Quote:
Quote:
, di sicuro e' potenzialmente pericolosa.Questo perche' se io mi faccio generare un nome di file E poi non creo subito il file E un attaccante crea il file al posto mio (visto che il nome e' facilmente indovinabile) E poi io creo il file piu' tardi senza controllare se c'e' gia', allora c'e' un rischio di sicurezza e quindi in generale conviene mkstemp. Ma direi che nel nostro caso non e' cosi' importante, visto che la necessita' e' solo quella di visualizzare su un altro schermo mentre si fanno delle prove.
__________________
One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. —Guy Steele |
||
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 07:24.












non so cosa HO bevuto quella sera, ma è ovvio che era qualcosa di forte perchè è naturale che ritorni quella del padre visto che il processo figlio è collegato a quel terminale.
, di sicuro e' potenzialmente pericolosa.








