La creazione di un altro file è più un problema che altro. Creare invece una directory e controllare il risultato della creazione. Il manuale Unix afferma che solo una attività può riuscire a creare una directory, l'altra otterrà un errore se la directory esiste già, incluso il caso in cui 2 task lo ha provato nello stesso momento. Il sistema operativo stesso gestisce il problema in modo da non doverlo fare.
Se non fosse per eventuali blocchi bloccati, è tutto quello che dovresti fare. Tuttavia, le cose accadono, i programmi si interrompono e non rimuovono sempre il blocco. Quindi l'implementazione può essere un po 'più elaborata.
In uno script ho spesso utilizzato il codice seguente. Gestisce automaticamente le serrature obsolete. È possibile implementare la stessa in C. pagina Cerca man:
man -s 2 mkdir
EXECUTION_CONTROL_FILE: è un percorso nome e il nome Dir, qualcosa come/usr/tmp/myAppName
second_of_now: restituire l'ora corrente in secondi (riportato qui di seguito)
LOCK_MAX_TIME: è quanto tempo in secondi una lattina di blocco esiste prima di essere considerato stantio
sonno 5: e 'sempre presume che un blocco farà qualcosa di breve e dolce. In caso contrario, forse il tuo ciclo del sonno dovrebbe essere più lungo.
LockFile() {
L_DIR=${EXECUTION_CONTROL_FILE}.lock
L_DIR2=${EXECUTION_CONTROL_FILE}.lock2
(
L_STATUS=1
L_FILE_COUNT=2
L_COUNT=10
while [ $L_STATUS != 0 ]; do
mkdir $L_DIR 2>/dev/null
L_STATUS=$?
if [ $L_STATUS = 0 ]; then
# Create the timetime stamp file
second_of_now >$L_DIR/timestamp
else
# The directory exists, check how long it has been there
L_NOW=`second_of_now`
L_THEN=`cat $L_DIR/timestamp 2>/dev/null`
# The file does not exist, how many times did this happen?
if [ "$L_THEN" = "" ]; then
if [ $L_FILE_COUNT != 0 ]; then
L_THEN=$L_NOW
L_FILE_COUNT=`expr $L_FILE_COUNT - 1`
else
L_THEN=0
fi
fi
if [ `expr $L_NOW - $L_THEN` -gt $LOCK_MAX_TIME ]; then
# We will try 10 times to unlock, but the 10th time
# we will force the unlock.
UnlockFile $L_COUNT
L_COUNT=`expr $L_COUNT - 1`
else
L_COUNT=10 # Reset this back in case it has gone down
sleep 5
fi
fi
done
)
L_STATUS=$?
return $L_STATUS
}
####
#### Remove access lock
####
UnlockFile() {
U_DIR=${EXECUTION_CONTROL_FILE}.lock
U_DIR2=${EXECUTION_CONTROL_FILE}.lock2
(
# This 'cd' fixes an issue with UNIX which sometimes report this error:
# rm: cannot determine if this is an ancestor of the current working directory
cd `dirname "${EXECUTION_CONTROL_FILE}"`
mkdir $U_DIR2 2>/dev/null
U_STATUS=$?
if [ $U_STATUS != 0 ]; then
if [ "$1" != "0" ]; then
return
fi
fi
trap "rm -rf $U_DIR2" 0
# The directory exists, check how long it has been there
# in case it has just been added again
U_NOW=`second_of_now`
U_THEN=`cat $U_DIR/timestamp 2>/dev/null`
# The file does not exist then we assume it is obsolete
if [ "$U_THEN" = "" ]; then
U_THEN=0
fi
if [ `expr $U_NOW - $U_THEN` -gt $LOCK_MAX_TIME -o "$1" = "mine" ]; then
# Remove lock directory as it is still too old
rm -rf $U_DIR
fi
# Remove this short lock directory
rm -rf $U_DIR2
)
U_STATUS=$?
return $U_STATUS
}
####
second_of_now() {
second_of_day `date "+%y%m%d%H%M%S"`
}
####
#### Return which second of the date/time this is. The parameters must
#### be in the form "yymmddHHMMSS", no centuries for the year and
#### years before 2000 are not supported.
second_of_day() {
year=`printf "$1\n"|cut -c1-2`
year=`expr $year + 0`
month=`printf "$1\n"|cut -c3-4`
day=`printf "$1\n"|cut -c5-6`
day=`expr $day - 1`
hour=`printf "$1\n"|cut -c7-8`
min=`printf "$1\n"|cut -c9-10`
sec=`printf "$1\n"|cut -c11-12`
sec=`expr $min \* 60 + $sec`
sec=`expr $hour \* 3600 + $sec`
sec=`expr $day \* 86400 + $sec`
if [ `expr 20$year % 4` = 0 ]; then
bisex=29
else
bisex=28
fi
mm=1
while [ $mm -lt $month ]; do
case $mm in
4|6|9|11) days=30 ;;
2) days=$bisex ;;
*) days=31 ;;
esac
sec=`expr $days \* 86400 + $sec`
mm=`expr $mm + 1`
done
year=`expr $year + 2000`
while [ $year -gt 2000 ]; do
year=`expr $year - 1`
if [ `expr $year % 4` = 0 ]; then
sec=`expr 31622400 + $sec`
else
sec=`expr 31536000 + $sec`
fi
done
printf "$sec\n"
}
Usa come questo:
# Make sure that 2 operations don't happen at the same time
LockFile
# Make sure we get rid of our lock if we exit unexpectedly
trap "UnlockFile mine" 0
.
. Do what you have to do
.
# We need to remove the lock
UnlockFile mine
Molto buona domanda . Non riesco a pensare a nessuna circostanza in cui ciò accada, a meno che due processi in conflitto abbiano entrambi scelto lo stesso nome di file unico allo stesso tempo (il che ovviamente sarebbe negativo). Potrebbe essere una soluzione alternativa per vecchi bug NFS? – Celada
Hai bisogno di creare lockfile su NFS?AFAIK dovresti essere in grado di usare 'flock()' o 'lockf()' nella maggior parte dei casi. – Hasturkun