2012-07-05 9 views
6

QNX (Neutrino 6.5.0) utilizza un'implementazione open source di ksh come sua shell. Un sacco di script forniti, tra gli script di avvio del sistema, l'uso costruisce come ad esempioDifferenza tra "test -a file" e "test file -ef file"

if ! test /dev/slog -ef /dev/slog; then 
    # do something 
fi 

per controllare se esiste un gestore di risorse o no nel filesystem. Ho cercato e ho potuto trovare solo spiegazioni molto dray che controlli -ef per vedere se i due parametri sono in effetti lo stesso file. Poiché il nome file specificato è lo stesso, sembra ridursi a verificare che il file esista.

Ho verificato il comportamento di test -a e test -e (entrambi sembrano controllare l'esistenza di file di qualsiasi tipo di file in base ai vari documenti che ho letto) e sembrano funzionare anche.

C'è qualche differenza nelle verifiche eseguite tra -ef e -a/-e? Sta usando -ef un qualche tipo di tentativo di protezione contro una condizione di competizione nell'esistenza del file?

+0

Sembra che potrebbe, infatti, essere controllando che il file esiste per due differenti stat() chiama. La voce/dev viene rimossa dal driver/manager (ad es., Dopo essere stata arrestata) solo se qualcuno ne verifica l'esistenza? – jhfrontz

+0

@jhfrontz: Non sono del tutto sicuro di cosa intendi ma (ad esempio) lo pseudo dispositivo/dev/slog viene rimosso solo quando il driver viene ucciso, cosa che normalmente non avviene nel mezzo della chiamata a 'test' dal fa parte dello script iniziale di avvio del sistema. Nel caso normale di/dev/slog un processo può scrivere sul dispositivo per accedere a un file/console/memoria, e mentre può finire con un nome file diverso, il dispositivo esposto in/dev dovrebbe essere lo stesso di prima scrivi su/dev/slog. – tinman

+0

Sto speculando sul fatto che la statistica del dispositivo abbia qualche effetto collaterale (ad esempio, spingendo il macchinista/manager a fare una sorta di servizio di pulizia) in modo tale che, come la prima chiamata di stat(), da 'test', sia completata, il file/il dispositivo viene rimosso/sostituito dal driver, causando così al secondo stat() di ottenere informazioni diverse, causando a sua volta il 'test' di fallire. È passato un po 'di tempo da quando ho usato QNX, ma [la pagina man di slogger] (http: //www.qnx.com/developers/docs/6.3.0SP3/neutrino/utilities/s/slogger.html) suggerisce che ci sono effetti collaterali dall'interazione con/dev/slog (ad es., scollegando il file dal registro). – jhfrontz

risposta

4

La revisione dello strace sulla copia di Ubuntu Linux di ksh non rivela differenze sostanziali. Una chiamata a stat vs due.

$ strace test /tmp/tmp.geLaoPkXXC -ef /tmp/tmp.geLaoPkXXC 

mostrato questo:

mmap(NULL, 7220736, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f11dc80b000 
close(3)        = 0 
stat("/tmp/tmp.geLaoPkXXC", {st_mode=S_IFREG|0600, st_size=0, ...}) = 0 
stat("/tmp/tmp.geLaoPkXXC", {st_mode=S_IFREG|0600, st_size=0, ...}) = 0 
close(1)        = 0 
close(2)        = 0 

... mentre

$ strace test -a /tmp/tmp.geLaoPkXXC 

ha mostrato questo:

fstat(3, {st_mode=S_IFREG|0644, st_size=7220736, ...}) = 0 
mmap(NULL, 7220736, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f6b49e2b000 
close(3)        = 0 
stat("/tmp/tmp.geLaoPkXXC", {st_mode=S_IFREG|0600, st_size=0, ...}) = 0 
close(1)        = 0 
close(2)        = 0 

Uno stat contro due.

$ ksh --version 
    version   sh (AT&T Research) 93u 2011-02-08 
1

Non sappiamo come il codice usi la stat esattamente senza codice, dobbiamo trovare la differenza tramite il codice.

/* code for -ef */ 
return (stat (argv[op - 1], &stat_buf) == 0 
        && stat (argv[op + 1], &stat_spare) == 0 
        && stat_buf.st_dev == stat_spare.st_dev 
        && stat_buf.st_ino == stat_spare.st_ino); 


/* code for -e/-a */ 
    case 'a':     /* file exists in the file system? */ 
    case 'e': 
     return stat (argv[pos - 1], &stat_buf) == 0; 

Quindi, se i nomi sono gli stessi e due stat() con lo stesso nome restituirà lo stesso valore, allora, test -a/-e file è lo stesso di test file -ef file. Sappiamo che la prima condizione è vera, e sappiamo che la seconda condizione è anche vero dai commenti da @tinman