fbpx
Skip to main content

[LA] Linux avanzato 2008

  • COM_EASYSOCIAL_GUEST_NAME
  • Avatar di COM_EASYSOCIAL_GUEST_NAME
  • Visitatori
  • Visitatori
17 Anni 2 Mesi fa #82860 da COM_EASYSOCIAL_GUEST_NAME
Risposta da COM_EASYSOCIAL_GUEST_NAME al topic [LA] Linux avanzato 2008
Ritornando all'esercizio proposto: molto carino, solo che non veniva specificata la condizione di uscita nel caso che nessun clone trovi il file. Nel seguito inserisco il codice scritto da me: ho considerato che il padre fa una sleep di 30 e nel caso riceve un SIGUSR1 si sveglia e manda i SIGTERM, altrimenti uccide direttamente tutti i cloni creati (senza permetterli di scrivere nulla). E' chiaro inoltre che se il padre manda un SIGTERM ad un clone che sta ancora analizzando una directory, questo terminerà, ma non riuscirà a scrivere nulla sul file (il FILE NON TROVATO).
#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>

#define MAXCLONI 10

int pid[MAXCLONI];

struct elem{
	char * str;
	char * dir;
};

void gestore1(){

	printf("Arrivo messaggio SIGUSR1!!!\n");

	int k = 0;

	for(k = 0; k < MAXCLONI; k++){
		sleep(2);
		if(pid[k] != 0)
			kill(pid[k], SIGTERM);
	}
	
}

void terminazione(){
		
	printf("Arrivo messaggio SIGTERM!!!\n");

}

int funzclone(struct elem * e){

	printf("Creato clone %d\n", getpid());

	char * copia = (char *)malloc(strlen(e -> dir) + 1);
	strncpy(copia, e -> dir, strlen(e -> dir));

	copia[strlen(e -> dir) + 1] = '\0';

	int l = 0;

	while(copia[l] != '\0'){
		if(copia[l] == '/'){
			copia[l] = '_';			
		}
		l++;
	}
	
	printf("Apro il file %s!!!\n", copia);

	int fd = open(copia, O_RDWR | O_CREAT | O_TRUNC, 0777);

	if(fd < 0){
		printf("Impossibile aprire il file %s!!!\n", copia);
		return -1;
	}
	
	DIR * d;

	d = opendir(e -> dir);

	if(d == NULL){
		printf("Impossibile aprire la directory %s!!!\n", (e -> dir));
		return -1;
	}

	struct dirent * od = (struct dirent *)malloc(sizeof(struct dirent));

	int count = 0;
	int trovato = 0;

	while((od = readdir(d)) != NULL){
		if((DT_REG & (od -> d_type)) && !(DT_DIR & (od -> d_type))){
			write(fd, "Check: ", strlen("Check: "));
			write(fd, (e -> dir), strlen(e -> dir));
			write(fd, (od -> d_name), strlen(od -> d_name));
			write(fd, "\n", 1);
			count++;
			if(strncmp((od -> d_name), (e -> str), strlen(e -> str)) == 0){
				write(fd, "FILE TROVATO!\n", strlen("FILE TROVATO!\n"));
				trovato = 1;
				break;
			}
		}
		sleep(1);
	}

	if(count == 0){
		write(fd, "DIRECTORY VUOTA!\n", strlen("DIRECTORY VUOTA!\n"));
	}else if(trovato == 1){
		kill(getppid(), SIGUSR1);
	}

	int ret = closedir(d);

	if(ret < 0){
		printf("Impossibile chiudere la directory %s!!!\n", (e -> dir));
		return -1;
	}

	pause();	

	if(trovato == 0){
		write(fd, "FILE NON TROVATO!\n", strlen("FILE NON TROVATO\n"));
	}

	ret = close(fd);

	if(ret < 0){
		printf("Impossibile chiudere il file %s!!!\n", copia);
		return -1;
	}

	return 0;
}

int main(int argc, char * argv[]){

	if(argc < 3){
		printf("Argomenti mancanti: <nome programma> <stringa ricerca> <una o più directory con / alla fine (MAX 10)>!!!\n");
		return -1;
	}else{
	
		int i = 0;

		for(i = 0; i < MAXCLONI; i++)
			pid[i] = 0;

		i = 2;
		int j = 0;
		int * stack = NULL;

		signal(SIGUSR1, gestore1);
		signal(SIGTERM, terminazione);

		while(argv[i] != NULL){	
			stack = (int *)malloc(1024 * sizeof(int));
			struct elem * e = (struct elem *)malloc(sizeof(struct elem));
			e -> str = (char *)malloc(30);
			e -> dir = (char *)malloc(256);
			strncpy(e -> str, argv[1], strlen(argv[1]));
			strncpy(e -> dir, argv[i], strlen(argv[i]));
			pid[j] = clone((int (*)(void *))funzclone, &stack[1023], CLONE_VM | CLONE_FILES | CLONE_SIGHAND, e);

			if(pid[j] < 0){
				printf("Errore nella creazione del clone %d!!!\n", j);
				return -1;
			}
			i++;
			j++;
			if(j == (MAXCLONI - 1))
				break;
		}

		i = 0;

		sleep(30);

		int k = 0;

		for(k = 0; k < MAXCLONI; k++){
			if(pid[k] != 0)
				kill(pid[k], SIGKILL);
		}

		printf("Uccisi tutti i cloni!!!\n");

		sleep(3);
		
	}
	return 0;
}

Buon divertimento e fatemi sapere cosa ne pensate!!! Vo a pranzo!!!

Si prega Accedi o Crea un account a partecipare alla conversazione.

Di più
17 Anni 2 Mesi fa #82861 da chiara sabbatella

errata corrige no: (int)a, ma (int*)a


scusa, ho sbagliato d nuovo. Dovrebbe essere cosi?

int funz( void *p )
{
(struct struttura*)p;
printf( "%d", p->a );
}

A me cosi da errore anche se a occhio sembra corretto!


Con quel tipo di modifica ho questo tipo di errore:
clone.c: In function ‘funz’:
clone.c:21: warning: dereferencing ‘void *’ pointer
clone.c:21: error: request for member ‘a’ in something not a structure or union

qualche consiglio?

Si prega Accedi o Crea un account a partecipare alla conversazione.

  • COM_EASYSOCIAL_GUEST_NAME
  • Avatar di COM_EASYSOCIAL_GUEST_NAME
  • Visitatori
  • Visitatori
17 Anni 2 Mesi fa #82877 da COM_EASYSOCIAL_GUEST_NAME
Risposta da COM_EASYSOCIAL_GUEST_NAME al topic [LA] Linux avanzato 2008

errata corrige no: (int)a, ma (int*)a


scusa, ho sbagliato d nuovo. Dovrebbe essere cosi?

int funz( void *p )
{
(struct struttura*)p;
printf( "%d", p->a );
}

A me cosi da errore anche se a occhio sembra corretto!


Con quel tipo di modifica ho questo tipo di errore:
clone.c: In function ‘funz’:
clone.c:21: warning: dereferencing ‘void *’ pointer
clone.c:21: error: request for member ‘a’ in something not a structure or union

qualche consiglio?


int funz( void *p )
{
printf( "%d", ((struct struttura*) p)->a );
}

Si prega Accedi o Crea un account a partecipare alla conversazione.

  • COM_EASYSOCIAL_GUEST_NAME
  • Avatar di COM_EASYSOCIAL_GUEST_NAME
  • Visitatori
  • Visitatori
17 Anni 2 Mesi fa #82887 da COM_EASYSOCIAL_GUEST_NAME
Risposta da COM_EASYSOCIAL_GUEST_NAME al topic [LA] Linux avanzato 2008

Ritornando all'esercizio proposto: molto carino, solo che non veniva specificata la condizione di uscita nel caso che nessun clone trovi il file. Nel seguito inserisco il codice scritto da me: ho considerato che il padre fa una sleep di 30 e nel caso riceve un SIGUSR1 si sveglia e manda i SIGTERM, altrimenti uccide direttamente tutti i cloni creati (senza permetterli di scrivere nulla). E' chiaro inoltre che se il padre manda un SIGTERM ad un clone che sta ancora analizzando una directory, questo terminerà, ma non riuscirà a scrivere nulla sul file (il FILE NON TROVATO).

Buon divertimento e fatemi sapere cosa ne pensate!!! Vo a pranzo!!!


Ciao! In effetti non avevo specificato il comportamento nel caso di file non trovato...
Io ho pensato che comunque i cloni devono terminare la scansione se non ricevono segnali e scrivere File non trovato alla fine..
Il fatto di scrivere sempre FILE NON TROVATO era voluto proprio per complicare le cose.. Alla fine sono ricorso all'aiutino di un altro forum dove mi hanno instradato a usare una variabile globale usata dall'handler di sigTERM che viene controllata nel while principale dei cloni..
In questo modo funziona.. L'unico problema che rimane nel caso in cui le 2 cartelle siano simili e il file venga trovato in contemporanea, ma è un caso limite che non ho considerato..

La cosa interessante sarebbe estendere la ricerca anche alle sottocartelle e far scrivere il file con un'indentazione opportuna..

ecco il codice:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <dirent.h>
#include <signal.h>
#include <sched.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>

volatile int g_other_process_found_it = 0;
volatile int firstToEnd = 0;

struct args {
	char pathname[4096];
	char keyString[256];
};
typedef struct args Args;

void replaceChar(char *str, char old, char new)
{
	while (*str!='\0')
	{
		if (*str==old)
		{
			*str=new;
		}
		str++;
	}
	
}

void handlTERM(int signo)
{
	++g_other_process_found_it;
	printf("SIGTERM received by %d.\n",(int)getpid());
}

void handlerUSR1(int signo)
{
	printf("SIGUSR1 received from %d\n",(int)firstToEnd);
}

void printfilecontent(int fd)
{
	lseek(fd,0,SEEK_SET);
	char ch;
	while (read(fd,&ch,1)==1)
	{
		printf("%c",ch);
	}
}

int clone_func(void *arguments)
{
	Args *a=(Args *) arguments;
	pid_t pid=getpid(),ppid=getppid();
	char filename[256],scanning[256];
	size_t scanlen;
	int fd;

	*scanning='\0';
	strcpy(filename, a->pathname);
	replaceChar(filename,'/','_');
	
	printf("I am %d, son of %d, and I'll search for files whose name contains %s into %s. The results of my scan will be available in file '%s'\n",
	(int)pid,(int)ppid,a->keyString,a->pathname,filename);
	
	//I register here my handler
	struct sigaction saTERM ={.sa_handler=handlTERM};
	sigaction (SIGTERM,&saTERM,NULL);

	fd = open (filename,O_CREAT|O_WRONLY|O_TRUNC,0666);

	if (fd<0)
	{
		printf("BAD FILE OPEN in CLONE\n");
		return 1;
	}
	
	struct dirent *entry;
	DIR *dir;
	struct stat statbuff;

	dir=opendir(a->pathname);
	if (dir==NULL)
	{
		printf("BAD OPENDIR. Probably directory doesn't exist\n");
		return 1;
	}

	chdir(a->pathname); //I change the CWD of the process to its target
	while (!g_other_process_found_it&&(entry=readdir(dir))!=NULL)
	{
		sleep(1);

		if (lstat(entry->d_name,&statbuff)<0)
		{
			printf("BAD lstat\n");
			return 1;
		}
		if (S_ISREG(statbuff.st_mode))
		{
			if (strcmp(".",entry->d_name)!=0 && strcmp ("..",entry->d_name)!=0) //I don't consider . and .. entries
			{
				//First I do write the filename into the file
				strcpy(scanning,entry->d_name);
				strcat(scanning,"\n");
				scanlen = strlen(scanning);
				write(fd,scanning,scanlen);
				//then I chech whether I'm finished
				if (strstr(scanning, a->keyString))
				{
					strcpy(scanning,"String found!!\n");
					scanlen=strlen(scanning);
					write(fd,scanning,scanlen);
					//I don't care of coming back to my old CWD
					close(fd);
					firstToEnd=pid;
					kill(ppid,SIGUSR1);// I notify the father

					return 0;
				}
			}
		}
	}
	//The search finished in an unsuccessfull way (file not found or another process found it)
	strcpy(scanning,"String NOT found!!\n");
	scanlen=strlen(scanning);
	write(fd,scanning,scanlen);
	close(fd);

	return 0;
}


int main (int argc, char *argv[])
{
	if (argc<3)
	{
		printf("usage: filename keystring searchdir1 searchdir2 ...\n");
		return 1;
	}

	int numClones=argc-2;

	int *stackClones;
	stackClones = malloc(sizeof(int)*1024*numClones);
	if (stackClones==NULL)
	{
		return 1;
	}

	pid_t *pidClones;
	pidClones = malloc (sizeof(pid_t)*numClones);
	if (pidClones==NULL)
	{
		return 1;
	}

	struct sigaction sa={.sa_handler=handlerUSR1};
	sigaction (SIGUSR1,&sa,0);
	int i;
	Args *ar;
	ar=malloc (sizeof(Args)*numClones);
	if (ar==NULL)
	{
		return 1;
	}

	for (i=0;i<numClones;i++)
	{
		strcpy(ar[i].pathname,argv[2+i]);
		strcpy(ar[i].keyString,argv[1]);

		pidClones[i]=clone(clone_func,stackClones+((i+1)*1023)*sizeof(int),CLONE_VM,&ar[i]);
		if (pidClones[i]<0)
		{
			printf("BAD CLONE\n");
			return 1;
		}
	}
	pid_t pid;
	int j;
	//I do wait all the children to finish (supposing that none of them will find the file)
	for (i=0;i<numClones;i++)
	{	
		pid=waitpid(-1,NULL,__WCLONE);
		if (firstToEnd!=0) break;
		printf("CLONE %d ENDED NORMALLY\n",(int)pid);
		//Now I set the pid of the normally terminated clone to 0 so that I'll not send a SIGTERM to it in the case another clone will
		//find the file
		for(j=0;j<numClones;j++)
			if (pidClones[j]==pid) pidClones[j]=0;
		
	}
	//I am here either because I received a SIGUSR1 either because all the clones terminated
	for (i=0;i<numClones;i++)
	{
		if (pidClones[i]!=firstToEnd&&pidClones[i]>0)
		{
			kill(pidClones[i],SIGTERM);
			printf("SIGTERM sent to %d\n",(int)pidClone

Ogni commento è piu' che benvenuto! :) ciao

Si prega Accedi o Crea un account a partecipare alla conversazione.

  • COM_EASYSOCIAL_GUEST_NAME
  • Avatar di COM_EASYSOCIAL_GUEST_NAME
  • Visitatori
  • Visitatori
17 Anni 2 Mesi fa #82889 da COM_EASYSOCIAL_GUEST_NAME
Risposta da COM_EASYSOCIAL_GUEST_NAME al topic [LA] Linux avanzato 2008
ops manca il pezzo finale del codice...
}
	}
	printf("THE END\n");
	return 0;
}

Si prega Accedi o Crea un account a partecipare alla conversazione.

  • COM_EASYSOCIAL_GUEST_NAME
  • Avatar di COM_EASYSOCIAL_GUEST_NAME
  • Visitatori
  • Visitatori
17 Anni 2 Mesi fa #82894 da COM_EASYSOCIAL_GUEST_NAME
Risposta da COM_EASYSOCIAL_GUEST_NAME al topic [LA] Linux avanzato 2008
Riposto il mio con le modifiche....
#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>

#define MAXCLONI 10

int pid[MAXCLONI];

int uscita = 0;
int fatto = 0;

struct elem{
	char * str;
	char * dir;
};

void gestore1(){

	printf("Arrivo messaggio SIGUSR1 su clone %d!!!\n", getpid());

	if(fatto == 0){
		int k = 0;

		for(k = 0; k < MAXCLONI; k++){
			sleep(1);
			if(pid[k] != 0)
				kill(pid[k], SIGTERM);
		}
	
		fatto = 1;
	}
}

void terminazione(){
		
	printf("Arrivo messaggio SIGTERM su %d!!!\n", getpid());
	uscita = 1;
}

int funzclone(struct elem * e){

	printf("Creato clone %d\n", getpid());
	sched_yield();

	char * copia = (char *)malloc(strlen(e -> dir) + 1);
	strncpy(copia, e -> dir, strlen(e -> dir));

	copia[strlen(e -> dir) + 1] = '\0';

	int l = 0;

	while(copia[l] != '\0'){
		if(copia[l] == '/'){
			copia[l] = '_';			
		}
		l++;
	}
	
	printf("Apro il file %s!!!\n", copia);

	int fd = open(copia, O_RDWR | O_CREAT | O_TRUNC, 0777);

	if(fd < 0){
		printf("Impossibile aprire il file %s!!!\n", copia);
		return -1;
	}
	
	DIR * d;

	d = opendir(e -> dir);

	if(d == NULL){
		printf("Impossibile aprire la directory %s!!!\n", (e -> dir));
		return -1;
	}

	struct dirent * od = (struct dirent *)malloc(sizeof(struct dirent));

	int count = 0;
	int trovato = 0;

	while((od = readdir(d)) != NULL){
		if(uscita == 0){
			if((DT_REG & (od -> d_type)) && !(DT_DIR & (od -> d_type))){
				write(fd, "Check: ", strlen("Check: "));
				write(fd, (e -> dir), strlen(e -> dir));
				write(fd, (od -> d_name), strlen(od -> d_name));
				write(fd, "\n", 1);
				count++;
				if(strncmp((od -> d_name), (e -> str), strlen(e -> str)) == 0){
					write(fd, "FILE TROVATO!\n", strlen("FILE TROVATO!\n"));
					trovato = 1;
					break;
				}
			}
			usleep(600);
		}else{
			break;
		}
	}

	if(count == 0){
		write(fd, "DIRECTORY VUOTA!\n", strlen("DIRECTORY VUOTA!\n"));
	}else if(trovato == 1){
		kill(getppid(), SIGUSR1);
	}

	int ret = closedir(d);

	if(ret < 0){
		printf("Impossibile chiudere la directory %s!!!\n", (e -> dir));
		return -1;
	}

	pause();

	if(trovato == 0){
		write(fd, "FILE NON TROVATO!\n", strlen("FILE NON TROVATO\n"));
	}

	ret = close(fd);

	if(ret < 0){
		printf("Impossibile chiudere il file %s!!!\n", copia);
		return -1;
	}

	return 0;
}

int main(int argc, char * argv[]){

	if(argc < 3){
		printf("Argomenti mancanti: <nome programma> <stringa ricerca> <una o più directory con / alla fine (MAX 10)>!!!\n");
		return -1;
	}else{
	
		int i = 0;

		for(i = 0; i < MAXCLONI; i++)
			pid[i] = 0;

		i = 2;
		int j = 0;
		int * stack = NULL;

		signal(SIGUSR1, gestore1);
		signal(SIGTERM, terminazione);

		while(argv[i] != NULL){	
			stack = (int *)malloc(1024 * sizeof(int));
			struct elem * e = (struct elem *)malloc(sizeof(struct elem));
			e -> str = (char *)malloc(30);
			e -> dir = (char *)malloc(256);
			strncpy(e -> str, argv[1], strlen(argv[1]));
			strncpy(e -> dir, argv[i], strlen(argv[i]));
			pid[j] = clone((int (*)(void *))funzclone, &stack[1023], CLONE_VM | CLONE_FILES | CLONE_SIGHAND, e);

			if(pid[j] < 0){
				printf("Errore nella creazione del clone %d!!!\n", j);
				return -1;
			}
			i++;
			j++;
			if(j == (MAXCLONI - 1))
				break;
		}

		i = 0;

		sleep(30);

		if(fatto == 0){
			int k = 0;

			for(k = 0; k < MAXCLONI; k++){
				sleep(2);
				if(pid[k] != 0)
					kill(pid[k], SIGTERM);
			}
			sleep(4);
		}

		sleep(2);
		printf("Tutti i cloni sono morti!!!\n");
		
	}
	return 0;
}
Ciao.....

Si prega Accedi o Crea un account a partecipare alla conversazione.