PDA

View Full Version : nuovo progetto x l'univ


khri81
03-05-2005, 18:18
dopo il precedente andato a buon fine x fortuna, anche grazie ai vostri consigli mi serve di nuovo un aiutino, ovviamente nn chiedo che lo facciate voi ma che mi possiate dare qualche dritta su come poter fare il prog, questo è ciò che il prof vuole:

Scrivete un programma C che agisca da interprete di comandi per il kernel Linux. La shell dovrebbe usare lo stesso stile della Bourne shell per eseguire i comandi.
I passi che devono essere compiuti dalla shell sono:

1. stampare il prompt – quando la shell parte dovrebbe cercare il nome della
macchina sulla quale è in esecuzione in modo che il prompt abbia il seguente
formato nome_macchina:directory_corrente>. Inoltre ogni volta che viene
utilizzato il comando cd per spostarsi nel file system, il prompt venga modificato
di conseguenza.

2. prelevare la riga di comando – la shell deve eseguire una operazione di lettura
del comando terminato da un carattere di NEWLINE (‘\n’).

3. analisi del comando – analisi della riga di comando a partire da sinistra verso
destra. La sintassi del comando è la seguente identificatore [identificatore
[identificatore]] dove il primo identificatore indica il comando mentre i restanti
sono i parametri del comando stesso. Ogni identificatore è separato dagli altri da
caratteri tipo: space, tab, oppure NEWLINE.

4. ricerca del file del comando – la shell fornisce un insieme di variabili di
ambiente. Tra queste la variabile di ambiente PATH contiene una lista ordinata di
pathname dove la shell dovrebbe ricercare il comando.

5. preparazione dei parametri – la shella prepara i parametri per il comando
inserendoli in un vettore di stringhe tipo char *argv[].

6. esecuzione del comando – la shell esegue il comando utilizzando un processo
figlio creato tramite una fork(), il quale chiama ad esempio execve() mentre il
processo padre invoca una wait().

Conviene svolgere il compito nei seguenti passi:
- Strutturate la shell in modo che inizi le variabili necessarie ed esegua un loop
senza fine a meno di non rivelare una condizione di EOF sullo stdin (esempio il
carattere Ctrl-D). Scrivete una versione che presenti un prompt, attenda un
comando dall’utente, legga il comando e lo stampi a schermo.

- Successivamente analizzate la riga di comando in modo da separare il comando e i parametri che dovreste porre in un vettore char *argv[]. Inoltre dovreste
calcolare il valore di int argc. Stampate a schermo il contenuto di argc e argv[].
Dovreste individuare un comando di exit per terminare la shell.

Un possibile schema per la shell potrebbe essere il seguente:

int main(){

struct command_struct {
char *name;
char *argv[];

} *command;


//inizializzazione della shell
..
//Loop principale
while (stdin non è EOF){
print_to_stdout(prompt_string);
command_line=read_from_stdin();
// determinate il nome del comando ed i parametri

// eseguite il comando con i parametri specificati

}
// terminate la shell
….
}
- Utilizzate argv[0] per localizzare il file eseguibile. In questa versione semplificata di shell, stampiamo il nome del file.

• Costruiamo una versione che ricerchi il comando tra i file presenti nella
directory corrente.

• Miglioriamo il programma in modo che trovi il comando tra i file
specificati con un pathname assoluto.

• Rendiamo possibile la ricerca nell’elenco delle directory presenti nella
variabile di ambiente PATH.
- Creiamo un processo figlio che esegua il comando (utilizzate la chiamata
execve()).

if( fork() == 0) {
// processo figlio
// viene eseguito nello stesso ambiente del padre
execvp(full_pathname,command->argv,0);
}
else {
// processo genitore
wait(&status);
}

- Implementiamo la possibilità che il comando venga eseguito in background dalla
shell: il processo padre (shell) non esegue una wait(), ma ripresenta il prompt. In
questo caso è possibile la presenza di processi zombie che vanno eliminati con
una gestione del segnale SIGCHLD.
- Prevediamo la possibilità di gestire la redirezione dello standard input (<
input_file), dello standard output (> output_file), della pipeline (cmd1 | cmd2)


raga aiuto nn so da dove cominciare e nemmeno cosa fare. :(

khri81
04-05-2005, 12:31
help raga ho una settimana di tempo x farlo!

VegetaSSJ5
04-05-2005, 16:10
non so quanto possa esserti utile ma prova a guardare questo:

http://www.dimi.uniud.it/~scagnett/LABSO/lezione15.pdf

VICIUS
04-05-2005, 17:50
1. stampare il prompt – quando la shell parte dovrebbe cercare il nome della
macchina sulla quale è in esecuzione in modo che il prompt abbia il seguente
formato nome_macchina:directory_corrente>. Inoltre ogni volta che viene
utilizzato il comando cd per spostarsi nel file system, il prompt venga modificato
di conseguenza.
per il nome del host apri il file /etc/hostname è l'unica parola cche c'è scritta al suo interno
per il nome della directory dovrebbe esserci una funzione... penso :)

2. prelevare la riga di comando – la shell deve eseguire una operazione di lettura
del comando terminato da un carattere di NEWLINE (‘\n’).
questo è facile puoi gia cominciare a scriverlo

3. analisi del comando – analisi della riga di comando a partire da sinistra verso
destra. La sintassi del comando è la seguente identificatore [identificatore
[identificatore]] dove il primo identificatore indica il comando mentre i restanti
sono i parametri del comando stesso. Ogni identificatore è separato dagli altri da
caratteri tipo: space, tab, oppure NEWLINE.
anche qui si fa tutto con un ciclo.

4. ricerca del file del comando – la shell fornisce un insieme di variabili di
ambiente. Tra queste la variabile di ambiente PATH contiene una lista ordinata di
pathname dove la shell dovrebbe ricercare il comando.
qui puoi usare strtok per separare i vari percorsi separati da ':'. per avere la variabile d'ambiente dai un' occhiata alla funzione getnev. ma soprattutto alla funzione stat per controlalre se esiste il file.

5. preparazione dei parametri – la shella prepara i parametri per il comando
inserendoli in un vettore di stringhe tipo char *argv[].
questo non dovresti averere problemi.

6. esecuzione del comando – la shell esegue il comando utilizzando un processo
figlio creato tramite una fork(), il quale chiama ad esempio execve() mentre il
processo padre invoca una wait().
anche qui basta leggere come funziona la funzione nel man e si capisce tutto. L'unca cosa rognosa è quando i processi vanno in background quindi devi gestire SIGCHLD. QUindi leggi bene come funziona signal

ciao ;)

khri81
06-05-2005, 11:40
4. ricerca del file del comando – la shell fornisce un insieme di variabili di
ambiente. Tra queste la variabile di ambiente PATH contiene una lista ordinata di
pathname dove la shell dovrebbe ricercare il comando.


allora io faccio cosi,

uso getenv ("PATH");

x cecare le varie dir e tra queste ci sono /usr/bin e /bin in cui stanno tutti i comandi, quello che mi chiedo è se devo tenere in considerazione /usr/bin oppure /bin????

o sono la stessa cosa???

khri81
06-05-2005, 12:13
i prime sei punti li ho praticamente fatti

il problema sta qui


- Implementiamo la possibilità che il comando venga eseguito in background dalla
shell: il processo padre (shell) non esegue una wait(), ma ripresenta il prompt. In
questo caso è possibile la presenza di processi zombie che vanno eliminati con
una gestione del segnale SIGCHLD.
- Prevediamo la possibilità di gestire la redirezione dello standard input (<
input_file), dello standard output (> output_file), della pipeline (cmd1 | cmd2)

cosa dovrei fare??? :eek:

VICIUS
06-05-2005, 17:17
- Implementiamo la possibilità che il comando venga eseguito in background dalla
shell: il processo padre (shell) non esegue una wait(), ma ripresenta il prompt. In
questo caso è possibile la presenza di processi zombie che vanno eliminati con
una gestione del segnale SIGCHLD.
prima di tutto creati un handler per il segnale SIGCHLD. Poi usi la funzione signal per assiciarlo a quel segnale. Poi non devi fare altro che distinguere i processi che hanno una '&' alla fine devono essere lanciati in background quindi non devi fare wait. gli altri invece ti comporti come prima.



- Prevediamo la possibilità di gestire la redirezione dello standard input (<
input_file), dello standard output (> output_file), della pipeline (cmd1 | cmd2)

cosa dovrei fare??? :eek:
Qui si tratta semplicemente di sostituire dei fd con una dup. con '<' sostituisci stdin al programma con quello di un file aperto dalla tua shell. Con '>' sostituisci stdout e con '|' non devi far altro che sostituire lo stdin del secondo programma con lo stdout del primo.

ciao ;)

khri81
11-05-2005, 15:43
aiuto da qui in poi:

6. esecuzione del comando – la shell esegue il comando utilizzando un processo
figlio creato tramite una fork(), il quale chiama ad esempio execve() mentre il
processo padre invoca una wait()

allora sono arrivato a vedere se il comando esiste oppure no, a dividere i parametri e il comando, ecc, adesso sono alla parte in cui devo eseguire il comando con eventuali parametri come faccio???

nn so bene l'uso delle fork ecc. chi mi aiuta, purtroppo nn ho tempo x vedere la documentazione!!! :(

VegetaSSJ5
11-05-2005, 17:56
qua trovi tutto:


http://www.dimi.uniud.it/~scagnett/LABSO/lezione14.pdf

sukoy27k
11-05-2005, 18:05
aiuto da qui in poi:

6. esecuzione del comando – la shell esegue il comando utilizzando un processo
figlio creato tramite una fork(), il quale chiama ad esempio execve() mentre il
processo padre invoca una wait()

allora sono arrivato a vedere se il comando esiste oppure no, a dividere i parametri e il comando, ecc, adesso sono alla parte in cui devo eseguire il comando con eventuali parametri come faccio???

nn so bene l'uso delle fork ecc. chi mi aiuta, purtroppo nn ho tempo x vedere la documentazione!!! :(
fondamenti di sis op:
la fork() duplica lo spazzio di indirizzamento del padre(copia il pcb del padre,appena tenta di leggere o scrivere gli vengono assegnate della pagine)a questo punto puoi decidere se sostituire lo spazio con una nuova immaggini che carichi attraverso una delle chiamate della famiglia delle exec,questo è il prototipo di quella che il prof ti ha chiesto di usare :
int execve(const char *filename, char *const argv[], char *const envp[])

in breve: nome,un elenco di argomenti che hai caricati in argv e l'enviorment che tolti alcuni casi non ti dovrebbe servire,in ogni caso fai riferimento a questa pagina che ti spiega bene tutta la famiglia delle API exec :
http://www.lilik.it/~mirko/gapil/gapilsu42.html

ti ricordo che fork() restituisce pid pari a 0 al filgio appena duplicato mentre restituisce il pid del filgio al padre che ha invocato la fork().
all'interno del processo shell la fork dovrà così essere usata:

pid=fork();
if(pid==0){//sei nel figlio quindi chiama la exec
execve("pippo",argv,NULL);
}
//pid !=0 ciò significa che sei nel padre,fai un controllo per eventuali errori
if (pid<0) //per qualche motivo il sis op nega la creazione di un nuovo processo,solitamente per mancanza di memoria ram

qui puoi chiamare sia wait(&stato)-attende la morte di un qualsiasi processo in questo caso ti andrebbbe bene,visto che ne crei uno solo-oppure waitpid(pid,&stato)che attende il processo contrassegnato da pid.
in stato ti ritorna lo stato del processo terminato.

per tutto questo fai riferimento al gapil che è molto chiaro,per il resto ti darei volentieri una mano ma ho da finire l'esercitazione sui grafi ;)

khri81
17-05-2005, 09:21
aiuto devo usare execve() ma nn riesco a farla andare chi mi fa un es di come si usa??? :(

VICIUS
17-05-2005, 12:45
aiuto devo usare execve() ma nn riesco a farla andare chi mi fa un es di come si usa??? :(
Questo qui sotto lancia ls -lhaR nella directory corrente. Ricorda che il promo argomento è sempre il nome del programma stesso ma senza percorso assoluto.
#include <stdio.h>
#include <unistd.h>

int main (int argc, char* argv[], char* envp[])
{
char* eseguibile = "/bin/ls";
char* argomenti[] = { "ls" , "-lhaR" , "." };

execve (eseguibile, argomenti, envp);
return 0;
}

ciao ;)

khri81
17-05-2005, 15:53
//esecuzione della fork
switch (pid = fork ())
{
case -1:
fatal ("fork failed");
break;
case 0:
printf ("comando execve %s\n", comando);
execve ("/bin/ls", NULL, NULL);
fatal ("exec failed");
break;
default:
wait ((int *)0);
//printf("ls completed\n");
//exit (0);
}

questa è il mio pezzo di prog che dovrebbe eseguire execve peccato che il comando ls io nn lo vedo eseuire!!!

VICIUS
17-05-2005, 17:13
//esecuzione della fork
switch (pid = fork ())
{
case -1:
fatal ("fork failed");
break;
case 0:
printf ("comando execve %s\n", comando);
execve ("/bin/ls", NULL, NULL);
fatal ("exec failed");
break;
default:
wait ((int *)0);
//printf("ls completed\n");
//exit (0);
}

questa è il mio pezzo di prog che dovrebbe eseguire execve peccato che il comando ls io nn lo vedo eseuire!!!
Se non lo devi eseguire che ci devi fare ? :confused:

ciao ;)

VegetaSSJ5
17-05-2005, 17:29
Se non lo devi eseguire che ci devi fare ? :confused:

ciao ;)
ha detto che non lo VEDE eseguire non che non lo deve eseguire... ;)

x khri81:
secondo ciò che ha detto vicius il primo argomento della execve è il percorso dell'eseguibile. il secondo argomento deve contenere almeno il nome dell'eseguibile, tu invece hai messo null. il terzo argomento invece deve essere il vettore dell'environment che è il terzo parametro del main.

VICIUS
17-05-2005, 17:37
ha detto che non lo VEDE eseguire non che non lo deve eseguire... ;)

x khri81:
secondo ciò che ha detto vicius il primo argomento della execve è il percorso dell'eseguibile. il secondo argomento deve contenere almeno il nome dell'eseguibile, tu invece hai messo null. il terzo argomento invece deve essere il vettore dell'environment che è il terzo parametro del main.
:eek: ho letto male. scusa.

ciao ;)

khri81
17-05-2005, 17:58
ha detto che non lo VEDE eseguire non che non lo deve eseguire... ;)

x khri81:
secondo ciò che ha detto vicius il primo argomento della execve è il percorso dell'eseguibile. il secondo argomento deve contenere almeno il nome dell'eseguibile, tu invece hai messo null. il terzo argomento invece deve essere il vettore dell'environment che è il terzo parametro del main.


nn va mettendo nel secondo parametro almeno il nome dell'eseguibile!!!

khri81
19-05-2005, 23:00
help :(