Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Renault Twingo E-Tech Electric: che prezzo!
Renault Twingo E-Tech Electric: che prezzo!
Renault annuncia la nuova vettura compatta del segmento A, che strizza l'occhio alla tradizione del modello abbinandovi una motorizzazione completamente elettrica e caratteristiche ideali per i tragitti urbani. Renault Twingo E-Tech Electric punta su abitabilità, per una lunghezza di meno di 3,8 metri, abbinata a un prezzo di lancio senza incentivi di 20.000€
Il cuore digitale di F1 a Biggin Hill: l'infrastruttura Lenovo dietro la produzione media
Il cuore digitale di F1 a Biggin Hill: l'infrastruttura Lenovo dietro la produzione media
Nel Formula 1 Technology and Media Centre di Biggin Hill, la velocità delle monoposto si trasforma in dati, immagini e decisioni in tempo reale grazie all’infrastruttura Lenovo che gestisce centinaia di terabyte ogni weekend di gara e collega 820 milioni di spettatori nel mondo
DJI Osmo Mobile 8: lo stabilizzatore per smartphone con tracking multiplo e asta telescopica
DJI Osmo Mobile 8: lo stabilizzatore per smartphone con tracking multiplo e asta telescopica
Il nuovo gimbal mobile DJI evolve il concetto di tracciamento automatico con tre modalità diverse, un modulo multifunzionale con illuminazione integrata e controlli gestuali avanzati. Nel gimbal è anche presente un'asta telescopica da 215 mm con treppiede integrato, per un prodotto completo per content creator di ogni livello
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 25-12-2006, 11:16   #1
Manugal
Senior Member
 
L'Avatar di Manugal
 
Iscritto dal: Jan 2001
Città: Villanova di Guidonia (RM)
Messaggi: 1079
[C] Gestione dei segnali

Ciao e auguri a tutti

Volevo sapere se questa è una giusta gestione del segnale SIGINT, perché quando faccio partire il programma e premo CTRL-C mi va in segmentation fault e non riesco a capirne la causa. Questo è il codice del main (ancora provvisorio):

Codice:
#include "functions.h"

int main(void){

int i;
pid_t pid;
int status;
ssize_t nread;
ssize_t nwrite;
struct sigaction sigint_handl;
char *buf=(char *)malloc(sizeof(char)*COMM_LENGTH);
char *name=(char *)malloc(sizeof(char)*COMM_LENGTH);

sigint_handl.sa_handler=sigint_handler;

if (sigemptyset(&sigint_handl.sa_mask)!=0){
   perror("sigemptyset failed"); 
   exit(SIGH_ERR); 
}

sigint_handl.sa_flags=0;

if(sigaction(SIGINT,&sigint_handl,NULL)){
   perror("sigaction failed");
   exit(SIGH_ERR);

}

setjmp(chdir_return);
setjmp(sigint_return);
while(1){
   sprintf(buf,"%s $  ", get_current_dir_name());

   if ((nwrite=write(STDOUT_FILENO,buf,COMM_LENGTH)) != COMM_LENGTH){
      perror("write error");
      if (buf!=NULL){
         free(buf);
         buf=NULL;
      }
      if (name!=NULL){
         free(name);
         name=NULL;
      }
      exit(ERR_GEN);
   } 
   if( (nread = read(STDIN_FILENO,buf,COMM_LENGTH)) <= 0){

       perror("read error");
       if (buf!=NULL){
         free(buf);
         buf=NULL;
      }
      if (name!=NULL){
         free(name);
         name=NULL;
      }
      exit(ERR_GEN);
   }  

   strcpy(name,buf);
   parse(name);
   if(command_lines(name) == OK){
      if((pid=fork()) < 0){
         perror("fork error");
         if (buf!=NULL){
            free(buf);
            buf=NULL;
         }
         if (name!=NULL){
            free(name);
            name=NULL;
         }
         exit(FORK_ERR);
      }
      if(pid > 0){
         if (waitpid(pid,&status,0) == -1){
            perror("waitpid error");
            if (buf!=NULL){
               free(buf);
               buf=NULL;
            }
            if (name!=NULL){
               free(name);
               name=NULL;
            }
         }
      }
   }
} 
return 0;
}
E questo quello del signal handler:

Codice:
#include "functions.h"

void sigint_handler(int signo){
   if(signo != SIGINT){
      printf("Something wrong, handler for SIGINT");
      exit(SIGH_ERR);  
   }
   else
      longjmp(sigint_return,0);
}
Grazie e buon natale a tutti.
Manugal è offline   Rispondi citando il messaggio o parte di esso
Old 25-12-2006, 12:03   #2
andbin
Senior Member
 
L'Avatar di andbin
 
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
Prendila come una mia opinione personale ... credo che non sia una buona idea mettere un longjmp() nell'handler.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%)
andbin è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 10:48   #3
Manugal
Senior Member
 
L'Avatar di Manugal
 
Iscritto dal: Jan 2001
Città: Villanova di Guidonia (RM)
Messaggi: 1079
Perché no? E come faccio a tornare qua "sprintf(buf,"%s $ ", get_current_dir_name());" (che sarebbe il prompt della shell)?
Manugal è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 10:54   #4
ilsensine
Senior Member
 
L'Avatar di ilsensine
 
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
In quel caso la read ritorna -1 con errno==EINTR.
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al
andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12
ilsensine è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 11:03   #5
Manugal
Senior Member
 
L'Avatar di Manugal
 
Iscritto dal: Jan 2001
Città: Villanova di Guidonia (RM)
Messaggi: 1079
Ah quindi dovrei controllare se la read torna EINTR (e se lo torna lanciare il signal handler) ? Un'altra possibilità. Mettiamo il caso che io voglia eseguire ls e mi trovo in una directory con tantissimi files. L'esecuzione di ls non è istantanea ma ci mette un po' per listare tutto il contenuto. Mettiamo il caso che durante l'esecuzione di ls premo CTRL-C. Visto che ls lo dovrei eseguire tramite una exec (a meno di altri suggerimenti da parte vostra ) , come faccio a fargli eseguire il mio signal handler dato che la exec di un comando riporta a default il gestore del segnale?

Grazie.
Manugal è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 11:21   #6
ilsensine
Senior Member
 
L'Avatar di ilsensine
 
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
Non ti seguo... il segnale viene inviato al tuo processo, non a ls
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al
andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12
ilsensine è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 11:31   #7
Manugal
Senior Member
 
L'Avatar di Manugal
 
Iscritto dal: Jan 2001
Città: Villanova di Guidonia (RM)
Messaggi: 1079
Cerco di spiegarmi meglio. Io per eseguire un comando con questa shell (perché in realtà il programma che sto realizzando è una shell) creo un figlio tramite fork() e faccio eseguire al figlio un comando tramite exec(). Il figlio eredita dal padre il signal handler impostato da me, ma nel momento in cui eseguo la exec di un comando, il signal handler ritorna quello di default. Io vorrei fare in modo (se possibile) di eseguire il mio signal handler dopo la exec. Per questo ti avevo fatto l'esempio di ls all'interno di una directory con migliaia di files, perché ad esempio mi stufo di vedere tutto il contenuto e ad un certo punto premo CTRL-C e ritorno al prompt. Spero di essere stato chiaro.
Manugal è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 11:59   #8
ilsensine
Senior Member
 
L'Avatar di ilsensine
 
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
Innanzitutto, non puoi passare un _tuo_ signal handler tramite exec, in quanto il tuo spazio di indirizzi (compreso il codice dell'handler!) viene completamente riscritto dalla exec.
Puoi intercettare il segnale dal processo principale e uccidere il child con un segnale, se è ciò che intendi fare.
Quote:
ma nel momento in cui eseguo la exec di un comando, il signal handler ritorna quello di default
Solo per il child, per il motivo che ti ho esposto.
Il parent continua ad utilizzare gli handler che ha definito.
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al
andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12
ilsensine è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 12:08   #9
Manugal
Senior Member
 
L'Avatar di Manugal
 
Iscritto dal: Jan 2001
Città: Villanova di Guidonia (RM)
Messaggi: 1079
Certo è proprio questo il problema, cioè che il child eseguendo la exec non ha più il signal handler del padre. E se faccio un controllo del tipo WIFSIGNALED(status) e WTERMSIG(status) al ritorno dalla wait? Potrei vedere se il figlio è stato terminato con un segnale e con quale segnale no? Però l'unica cosa è che quando so il segnale con il quale è stato terminato, se il segnale ad esempio è SIGINT, quale signal handler viene eseguito?

Grazie.
Manugal è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 12:13   #10
ilsensine
Senior Member
 
L'Avatar di ilsensine
 
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
Continuo a non capire...
Come può il child beccarsi un segnale in seguito a ctrl+c dalla console? E' impossibile, a meno che non hai per errore invocato la exec nel ramo del parent della fork e non nel ramo del child...
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al
andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12
ilsensine è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 12:21   #11
Manugal
Senior Member
 
L'Avatar di Manugal
 
Iscritto dal: Jan 2001
Città: Villanova di Guidonia (RM)
Messaggi: 1079
Allora facciamo così, cerco di fare un esempio. Il figlio tramite la funzione exec() esegue ls -l e riceve questo output:

file1
file2
file3
file4
file5
ecc.

Mettiamo il caso che i file all'interno della directory che sto listando sono tantissimi (sono 10000 file). Io non voglio aspettare che finisca di elencarli tutti (magari ci mette un po) quindi ad un certo punto, prima che finisce di elencare tutto il contenuto, premo CTRL-C. Una volta premuto dovrà eseguire un signal handler (che per forza di cose sarà quello di default dato che ho eseguito la exec()). Io però devo fare in modo di tornare a questa istruzione "sprintf(buf,"%s $ ", get_current_dir_name()); ed è per questo che mi serve il mio signal handler.
Manugal è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 12:29   #12
ilsensine
Senior Member
 
L'Avatar di ilsensine
 
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
Se posti un pò di codice forse possiamo intenderci meglio...
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al
andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12
ilsensine è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 12:35   #13
Manugal
Senior Member
 
L'Avatar di Manugal
 
Iscritto dal: Jan 2001
Città: Villanova di Guidonia (RM)
Messaggi: 1079
main.c

Codice:
#include "functions.h"

int main(void){

extern int errno;
int i;
pid_t pid;
int status;
ssize_t nread;
ssize_t nwrite;
struct sigaction sigint_handl;
char *buf=(char *)malloc(sizeof(char)*COMM_LENGTH);
char *name=(char *)malloc(sizeof(char)*COMM_LENGTH);

sigint_handl.sa_handler=sigint_handler;

if (sigemptyset(&sigint_handl.sa_mask)!=0){
   perror("sigemptyset failed"); 
   exit(SIGH_ERR); 
}

sigint_handl.sa_flags=0;

if(sigaction(SIGINT,&sigint_handl,NULL)){
   perror("sigaction failed");
   exit(SIGH_ERR);
}

while(1){
   sprintf(buf,"%s $  ", get_current_dir_name());

   if ((nwrite=write(STDOUT_FILENO,buf,COMM_LENGTH)) != COMM_LENGTH){
      perror("write error");
      if (buf!=NULL){
         free(buf);
         buf=NULL;
      }
      if (name!=NULL){
         free(name);
         name=NULL;
      }
      exit(ERR_GEN);
   } 
   if( (nread = read(STDIN_FILENO,buf,COMM_LENGTH)) <= 0){
      if(errno == EINTR)
         continue;
      else{
         if (buf!=NULL){
            free(buf);
            buf=NULL;
         }
         if (name!=NULL){
            free(name);
            name=NULL;
         }
         exit(ERR_GEN);
      }  
   }
   strcpy(name,buf);
   parse(name);
   if(command_lines(name) == OK){
      if((pid=fork()) < 0){
         perror("fork error");
         if (buf!=NULL){
            free(buf);
            buf=NULL;
         }
         if (name!=NULL){
            free(name);
            name=NULL;
         }
         exit(FORK_ERR);
      }
      if(pid == 0{
      
      if(pid > 0){
         if (waitpid(pid,&status,0) == -1){
            perror("waitpid error");
            if (buf!=NULL){
               free(buf);
               buf=NULL;
            }
            if (name!=NULL){
               free(name);
               name=NULL;
            }
         continue;
         }
         if(WIFSIGNALED(status))
            signoris=WTERMSIG(status);
      }
   }
} 
return 0;
}
functions.h
Codice:
/* Librerie */
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <ctype.h>
#include <unistd.h>
#include <signal.h>
#include <glob.h>
#include <errno.h>
#include <setjmp.h>
#include <sys/wait.h>
#include <sys/types.h>

/* Definizione di costanti */
#define MAX_ARGS     256         /* Numero massimo di argomenti sulla linea di comando */
#define COMM_LENGTH  256         /* Lunghezza massima di un comando */

/* Costanti per errori */
#define OK           0           /* OK */
#define F_NOTEXEC    1           /* File non eseguibile */
#define F_NOEXIST    2           /* Accesso negato o file inesistente */
#define ERR_GEN      3           /* Errore generico */
#define READ_ERR     4           /* Read error */
#define WRITE_ERR    5           /* Write error */
#define FORK_ERR     6           /* Fork error */
#define SIGH_ERR     7           /* Errore del signal handler */

/* Variabili globali */
char *args[MAX_ARGS];            /* Argomenti sulla linea di comando */
glob_t pglob;                    /* Variabile per il trattamento del filename expansion */

/* Definizione di funzioni */
int command_lines(char *);       /* Cerca la locazione del comando e restituisce il pathname completo */
void parse(char *);              /* Analizza il comando passato suddividendo gli argomenti */
void sigint_handler(int);        /* Signal handler per CTRL-C */
void sigquit_handler(int);       /* Signal handler per CTRL-\ */
sigint_handler.c
Codice:
#include "functions.h"

void sigint_handler(int signo){
   if(signo != SIGINT){
      printf("Something wrong, handler for SIGINT");
      exit(SIGH_ERR);  
   }
   else
      return;
}
Manugal è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 13:02   #14
ilsensine
Senior Member
 
L'Avatar di ilsensine
 
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
Codice:
      if(pid == 0{
      
      if(pid > 0){
!?
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al
andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12
ilsensine è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 13:16   #15
Manugal
Senior Member
 
L'Avatar di Manugal
 
Iscritto dal: Jan 2001
Città: Villanova di Guidonia (RM)
Messaggi: 1079
Il codice non è completo (mica ho finito tutto)

E quello è proprio il famoso ramo child che devo implementare (sempre che quella soluzione vada bene per quello che devo fare io).
Manugal è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 15:30   #16
ilsensine
Senior Member
 
L'Avatar di ilsensine
 
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
Comunque, come per le altre funzioni, in caso di segnale intercettato la waitpid ritorna -1 con errno==EINTR. Puoi, in questo caso, inviare manualmente un SIGTERM al child; ad es. qualcosa tipo:

Codice:
  if(pid > 0){
    if (waitpid(pid, &status, 0) == -1) {
      if (errno!=EINTR)
        perror("waitpid")
      else {
        kill(pid, SIGTERM);
/* necessario per evitare uno zombie */
        do {
         if (waitpid(pid, &status, 0)!=-1)
            break; 
        } while(errno==EINTR);
      }
      continue;
    } else {
      <ramo child>
    }
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al
andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12
ilsensine è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 16:04   #17
Manugal
Senior Member
 
L'Avatar di Manugal
 
Iscritto dal: Jan 2001
Città: Villanova di Guidonia (RM)
Messaggi: 1079
Ok però in questo caso sono io che mando un segnale esplicitamente. Io invece devo intercettare un segnale proveniente dal figlio (nel mio caso CTRL-C). Perché, ripeto, durante la exec() nel ramo child, nell'ipotesi in cui io prema CTRL-C deve partire il signal handler creato da me. Nel tuo codice:

Codice:
if (waitpid(pid, &status, 0) == -1) {
      if (errno!=EINTR)
        perror("waitpid")
      else {
        kill(pid, SIGTERM);
attendi che arrivi un segnale ma poi non capisco perché tu debba terminare il figlio con SIGTERM. Se io interrompo il figlio con SIGINT, ad esempio, la funzione waitpid() tornerà -1 quindi che bisogno c'è di riterminare il figlio con la kill()?
Manugal è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 16:32   #18
ilsensine
Senior Member
 
L'Avatar di ilsensine
 
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
Quote:
Originariamente inviato da Manugal
Ok però in questo caso sono io che mando un segnale esplicitamente. Io invece devo intercettare un segnale proveniente dal figlio (nel mio caso CTRL-C).
Non funziona così. Come può un segnale "partire dal figlio"?

Quote:
Perché, ripeto, durante la exec() nel ramo child, nell'ipotesi in cui io prema CTRL-C deve partire il signal handler creato da me.
Infatti parte, nel parent. Non nel child, per i motivi che ti ho detto.

Quote:
Se io interrompo il figlio con SIGINT, ad esempio, la funzione waitpid() tornerà -1
Se waitpid ritorna -1 vuol dire che è stata interrotta, non che il child è terminato.

Esercitati con questo programmino, modificandolo a tuo piacimento, per vedere come funziona il tutto:
Codice:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>

static void sigint_handler(int signo) {
	fprintf(stderr, "Caught signal %d\n", signo);
}

int main()
{
	struct sigaction sigint_handl;
	pid_t pid;
	
	sigint_handl.sa_handler = sigint_handler;
	sigemptyset(&sigint_handl.sa_mask);
	sigint_handl.sa_flags = 0;
	sigaction(SIGINT, &sigint_handl, NULL);

	pid = fork();
	if (pid==0) {
		char *args[] = { "sleep", "10", NULL };
		/* Senza setsid, il ctrl+c giunge anche al child. Potrebbe essere
		    desiderabile, oppure no.
		    Nota che un kill -INT <pid del parent> non giunge anche al child! */
		setsid();
		execv("/bin/sleep", args);
		perror("execv");
	} else {
		while(1) {
			int status;
			int ret = waitpid(pid, &status, 0);
			if (ret<0) {
				if (errno!=EINTR)
					perror("waitpid");
				else {
					fprintf(stderr, "Killing child...\n");
					/* Nel caso che:
					  * 1) Il segnale non sia stato inviato anche al child
					  *     (ad es. un SIGINT mandato direttamente al parent)
					  * 2) Il child gestisce e non termina su SIGINT
					  * allora accertiamoci di terminare il child manualmente.
					 */
					kill(pid, SIGTERM);
				}
			} else {
				fprintf(stderr, "Child done. status=%d\n", status);
				break;
			}
		}
	}
	return 0;
}
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al
andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12
ilsensine è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 16:37   #19
ilsensine
Senior Member
 
L'Avatar di ilsensine
 
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
...il tutto, beninteso, se ho capito cosa ti serve: su ctrl+c, accertarti che il child ("ls" nel tuo caso) sia annullato.
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al
andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12
ilsensine è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 16:39   #20
Manugal
Senior Member
 
L'Avatar di Manugal
 
Iscritto dal: Jan 2001
Città: Villanova di Guidonia (RM)
Messaggi: 1079
Ok, grazie ci proverò.
Manugal è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


Renault Twingo E-Tech Electric: che prezzo! Renault Twingo E-Tech Electric: che prezzo!
Il cuore digitale di F1 a Biggin Hill: l'infrastruttura Lenovo dietro la produzione media Il cuore digitale di F1 a Biggin Hill: l'infrast...
DJI Osmo Mobile 8: lo stabilizzatore per smartphone con tracking multiplo e asta telescopica DJI Osmo Mobile 8: lo stabilizzatore per smartph...
Recensione Pura 80 Pro: HUAWEI torna a stupire con foto spettacolari e ricarica superveloce Recensione Pura 80 Pro: HUAWEI torna a stupire c...
Opera Neon: il browser AI agentico di nuova generazione Opera Neon: il browser AI agentico di nuova gene...
Sony ULT WEAR in super offerta: le cuffi...
Sconti record su smartwatch top: Apple W...
NIU continua a crescere: a EICMA 2025 nu...
DJI Osmo 360 ai prezzi più bassi ...
Il nuovo Edge 70 conferma la strategia v...
Il Re dei mini PC economici: 160€ con 16...
Smartphone, tablet e auricolari a soli 2...
Square Enix guarda al futuro: più...
Crolla a 89€ una scopa elettrica low cos...
Anche Huawei segue il trend del mercato:...
Un portatile un tuttofare definitivo a 5...
PosteMobile passerà alla rete TIM...
I 6 migliori smartphone da acquistare su...
iPhone Air 2 è già in cant...
OnePlus 15, in Europa sarà uguale...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 10:06.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Served by www3v