Tuttola85
06-09-2013, 16:24
Ciao a tutti!
Scrivo perchè non ho capito a cosa serve la pimitiva dup() (UNIX - Linguaggio C). Mi spiego meglio:
#include <unistd.h>
retval=dup(fd);
int fd;
int retval;
Ho capito che fd è il file descriptor da duplicare e che retval è il nuovo file descriptor (con il numero più basso possibile nel sistema). Ma quando devo usarlo?
Vi posto un testo d'esame e la soluzione che dà la Prof.ssa. Qualcuno sa spiegarmi l'uso della dup()? Si poteva risolvere l'esercizio senza usarla?
GRAZIE MILLE!!
Testo:
...La parte C accetta un numero variabile di parametri (N) che rappresentano nomi di fle (F1, F2, ... , FN). Il processo padre deve generare N processi figli (P0, P1, ... PN-1): ogni processo figlio è associato al corrispondente file Fi. Ognuno di tali processi figli deve, usando in modo opportuno il comando head di UNIX/Linux, leggere la prima linea del file associato; tale linea deve essere quindi comunicata al padre. Per ogni figlio, il padre ha il compito di stampare su standard output, rispettando l'ordine dei file, l'indce del processo figlio, il nome del file corrispondente e la linea ricevuta. Al termine, ogni processo figlio deve ritornare al padre il valore di ritorno della head e il padre deve stampare su standard output il PID di ogni figlio e il valore ritornato.
Soluzione:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
typedef int pipe_t[2];
int main(int argc, char **argv) {
/* -------- Variabili locali ---------- */
int pid;
int N;
int status;
pipe_t *piped;
int i, j;
char ch;
/* ------------------------------------ */
/* Controllo sul numero di parametri */
if (argc < 2) /* Meno di due parametri */ {
printf("Errore nel numero dei parametri\n");
exit(1); }
/* Calcoliamo il numero di file passati */
N = argc - 1;
/* Allocazione dell'array di N pipe descriptors*/
piped = (pipe_t *) malloc (N*sizeof(pipe_t)); if (piped == NULL)
{
printf("Errore nella allocazione della memoria\n");
exit(2); }
/* Creazione delle N pipe padre-figli */
for (i=0; i < N; i++) {
}
if(pipe(piped[i]) < 0) {
printf("Errore nella creazione della pipe\n");
exit(3); }
/* Ciclo di generazione dei figli */
for (i=0; i < N; i++) {
if ( (pid = fork()) < 0) {
printf("Errore nella fork\n");
exit(4); }
if (pid == 0) {
/* codice del figlio */
printf("Sono il processo figlio di indice %d e pid %d sto per
leggere la prima linea del file %s\n", i, getpid(), argv[i+1]);
/* ogni figlio deve simulare il piping dei comandi
nei confronti del padre e quindi deve chiudere lo
standard output e quindi usare la dup sul lato di
scirttura della propria pipe */
close(1);
dup(piped[i][1]);
/* Chiusura di tutte le pipe */
for (j=0; j < N; j++) {
close(piped[j][0]);
close(piped[j][1]);
}
/* Ridirezione dello standard error su /dev/null
(per evitare messaggi di errore a video)*/
close(2);
open("/dev/null", O_WRONLY);
/* Il figlio diventa il comando head */
execlp("head", "head", "-1", argv[i+1], (char *)0);
/* Non si dovrebbe mai tornare qui!!*/
exit(1); /* torno un valore diverso da zero per indicare insuccesso*/
}
}
/* Codice del padre */
for (i=0; i < N; i++)
close(piped[i][1]);
/* Il padre recupera le informazioni dai figli in ordine di indice */
for (i=0; i < N; i++) {
printf("Il figlio di indice %d ha letto dal file %s la linea:\n", i,
argv[i+1]);
do
{
read(piped[i][0], &ch, 1);
printf("%c", ch);
}
while (ch != '\n');
}
/* Il padre aspetta i figli in ordine di indice */
for (i=0; i < N; i++) {
pid = wait(&status);
if (pid < 0)
{
printf("Errore in wait\n");
exit (5);
}
if ((status & 0xFF) != 0)
printf("Figlio con pid %d terminato in modo anomalo\n", pid);
else
printf("Il figlio con pid=%d ha ritornato %d\n", pid, (int)((status >> 8) & 0xFF));
La parte in grassetto è quella in cui mi perdo!! :(
Scrivo perchè non ho capito a cosa serve la pimitiva dup() (UNIX - Linguaggio C). Mi spiego meglio:
#include <unistd.h>
retval=dup(fd);
int fd;
int retval;
Ho capito che fd è il file descriptor da duplicare e che retval è il nuovo file descriptor (con il numero più basso possibile nel sistema). Ma quando devo usarlo?
Vi posto un testo d'esame e la soluzione che dà la Prof.ssa. Qualcuno sa spiegarmi l'uso della dup()? Si poteva risolvere l'esercizio senza usarla?
GRAZIE MILLE!!
Testo:
...La parte C accetta un numero variabile di parametri (N) che rappresentano nomi di fle (F1, F2, ... , FN). Il processo padre deve generare N processi figli (P0, P1, ... PN-1): ogni processo figlio è associato al corrispondente file Fi. Ognuno di tali processi figli deve, usando in modo opportuno il comando head di UNIX/Linux, leggere la prima linea del file associato; tale linea deve essere quindi comunicata al padre. Per ogni figlio, il padre ha il compito di stampare su standard output, rispettando l'ordine dei file, l'indce del processo figlio, il nome del file corrispondente e la linea ricevuta. Al termine, ogni processo figlio deve ritornare al padre il valore di ritorno della head e il padre deve stampare su standard output il PID di ogni figlio e il valore ritornato.
Soluzione:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
typedef int pipe_t[2];
int main(int argc, char **argv) {
/* -------- Variabili locali ---------- */
int pid;
int N;
int status;
pipe_t *piped;
int i, j;
char ch;
/* ------------------------------------ */
/* Controllo sul numero di parametri */
if (argc < 2) /* Meno di due parametri */ {
printf("Errore nel numero dei parametri\n");
exit(1); }
/* Calcoliamo il numero di file passati */
N = argc - 1;
/* Allocazione dell'array di N pipe descriptors*/
piped = (pipe_t *) malloc (N*sizeof(pipe_t)); if (piped == NULL)
{
printf("Errore nella allocazione della memoria\n");
exit(2); }
/* Creazione delle N pipe padre-figli */
for (i=0; i < N; i++) {
}
if(pipe(piped[i]) < 0) {
printf("Errore nella creazione della pipe\n");
exit(3); }
/* Ciclo di generazione dei figli */
for (i=0; i < N; i++) {
if ( (pid = fork()) < 0) {
printf("Errore nella fork\n");
exit(4); }
if (pid == 0) {
/* codice del figlio */
printf("Sono il processo figlio di indice %d e pid %d sto per
leggere la prima linea del file %s\n", i, getpid(), argv[i+1]);
/* ogni figlio deve simulare il piping dei comandi
nei confronti del padre e quindi deve chiudere lo
standard output e quindi usare la dup sul lato di
scirttura della propria pipe */
close(1);
dup(piped[i][1]);
/* Chiusura di tutte le pipe */
for (j=0; j < N; j++) {
close(piped[j][0]);
close(piped[j][1]);
}
/* Ridirezione dello standard error su /dev/null
(per evitare messaggi di errore a video)*/
close(2);
open("/dev/null", O_WRONLY);
/* Il figlio diventa il comando head */
execlp("head", "head", "-1", argv[i+1], (char *)0);
/* Non si dovrebbe mai tornare qui!!*/
exit(1); /* torno un valore diverso da zero per indicare insuccesso*/
}
}
/* Codice del padre */
for (i=0; i < N; i++)
close(piped[i][1]);
/* Il padre recupera le informazioni dai figli in ordine di indice */
for (i=0; i < N; i++) {
printf("Il figlio di indice %d ha letto dal file %s la linea:\n", i,
argv[i+1]);
do
{
read(piped[i][0], &ch, 1);
printf("%c", ch);
}
while (ch != '\n');
}
/* Il padre aspetta i figli in ordine di indice */
for (i=0; i < N; i++) {
pid = wait(&status);
if (pid < 0)
{
printf("Errore in wait\n");
exit (5);
}
if ((status & 0xFF) != 0)
printf("Figlio con pid %d terminato in modo anomalo\n", pid);
else
printf("Il figlio con pid=%d ha ritornato %d\n", pid, (int)((status >> 8) & 0xFF));
La parte in grassetto è quella in cui mi perdo!! :(