2014-06-26 17 views
5

Ben flock ve

$fp = fopen('/tmp/lock.txt', 'r+'); 
if(flock($fp, LOCK_EX | LOCK_NB, $wouldblock)) { 
    echo 'Lock obtained'; 
} 
else{ 
    echo 'Unable to obtain lock'; 
} 
fclose($fp); 

Belgeler wouldblock hakkında söylediği wouldblock argüman engelleme olmayan anlamaya çalışıyorum:

isteğe bağlı üçüncü argüman 1 olarak ayarlanır

kilit engellemek olsaydı (EWOULDBLOCK hatanum koşulu). Başka bir işlem kilidi kazanmıştır eğer bir testte çoğaltılması

, Sürü fonksiyonu immeditatly

Öyleyse neden ise yaklaşık $ wouldblock değeri önemsemeliyiz YANLIŞ (non engelleme) dönecek, eşzamanlı durumunu Enviroment engelleme olmayan modda akın işlevinin dönüş değeri, kilidin bana ulaşılamamış olduğunu söyler mi?

FALSE döndüren flock işlevi ile 1 olarak ayarlanan $ wouldblock argümanı ile $ wouldblock argümanının ne için yararlı olduğu arasındaki farkı alamıyorum.

cevap

8

Bunun nedeni, flock() yalnızca kilitleme zaten başka bir yerde kazanıldığından başarısız olabilir. Böyle bir durumda, kilidin serbest bırakılmasını beklemez, ancak hemen false döndürür. Başka bir deyişle, LOCK_NB ile akın yanlış döndürürse ve bunun anlamı = 1 ise o zaman kilitlenmeye çalışılır, ancak başka bir yerde kazanılmış demektir. Ama LOCK_NB ile akın yanlış döndürürse ve 0 olurmu olursa, o zaman gerçekten kötü bir şey demektir ve akın bile tamamen imkansız olduğu için kilitlenmeyi beklemeyi düşünmüyordu.

Kontrol dışarı bu kodu (here is also a gist):

<?php 
// Let's create /tmp/ninja-lock1.txt ... 
$fp0 = fopen('/tmp/ninja-lock1.txt', 'c'); 
// ... and close it imiedietly 
fclose($fp0); 

// File handler $fp0 was closed so flock() 
// is unable to use it to gain lock. 
// It will fail with wouldblock set to 0 
// as it doesn't make sense to wait on unusable file handle. 
// 
// BTW flock() throws in such case warning "x is not a valid stream resource". 
// Just for the purpose of clear output from this example 
// I've suppressed it with @ - don't use @ in production 
$flockResult = @flock($fp0, LOCK_EX | LOCK_NB, $wouldblock); 
printf("flock=%b; wouldblock=%d (Acquire lock: %s)\n", $flockResult, $wouldblock, "failure, broken file handle"); 

// Two handlers for /tmp/ninja-lock2.txt 
// to show flock() blocking result. 
$fp1 = fopen('/tmp/ninja-lock2.txt', 'c'); 
$fp2 = fopen('/tmp/ninja-lock2.txt', 'c'); 

// Nobody is locking on /tmp/ninja-lock2.txt, 
// so it will acquire lock and wouldblock will be 0 
$flockResult = flock($fp1, LOCK_EX | LOCK_NB, $wouldblock); 
printf("flock=%b; wouldblock=%d (Acquire lock: %s)\n", $flockResult, $wouldblock, "success"); 

// File is locked on $fp1 handle so flock won't acquire lock 
// and wouldblock will be 1 
$flockResult = flock($fp2, LOCK_EX | LOCK_NB, $wouldblock); 
printf("flock=%b; wouldblock=%d (Acquire lock: %s)\n", $flockResult, $wouldblock, "failure, already acquired somewhere else"); 

// Result: 
// $ php flock.php 
// flock=0; wouldblock=0 (Acquire lock: failure, broken file handle) 
// flock=1; wouldblock=0 (Acquire lock: success) 
// flock=0; wouldblock=1 (Acquire lock: failure, already acquired somewhere else) 
?> 
Ayrıca

sadece engelleme modunda gibi, EWOULDBLOCK kontrol LOCK_NB bayrağıyla sürünün() için sadece mantıklı dikkat etmek değer gelecek okuyucuların herhangi bir karışıklığa temizlemek için Ya başarı ve blok ya da başarısızlık ve blok yok.

Sen php source code for flock içine bakarak bunu görebilirsiniz:

PHPAPI int php_flock(int fd, int operation) 
#if HAVE_STRUCT_FLOCK /* {{{ */ 
{ 
    struct flock flck; 
    int ret; 

    flck.l_start = flck.l_len = 0; 
    flck.l_whence = SEEK_SET; 

    if (operation & LOCK_SH) 
     flck.l_type = F_RDLCK; 
    else if (operation & LOCK_EX) 
     flck.l_type = F_WRLCK; 
    else if (operation & LOCK_UN) 
     flck.l_type = F_UNLCK; 
    else { 
     errno = EINVAL; 
     return -1; 
    } 

    ret = fcntl(fd, operation & LOCK_NB ? F_SETLK : F_SETLKW, &flck); 

    if (operation & LOCK_NB && ret == -1 && 
      (errno == EACCES || errno == EAGAIN)) 
     errno = EWOULDBLOCK; 

    if (ret != -1) ret = 0; 

    return ret; 
} 

EWOULDBLOCK yalnızca operation & LOCK_NB && ret == -1 && (errno == EACCES || errno == EAGAIN) ayarlanır.

sen de F_SETLK ve F_SETLKW hakkında man page of fcntl, çoğunlukla parçalar okuyabilir uygulanmasında daha ilgileniyorsanız: (l_type F_RDLCK veya F_WRLCK olduğunda)

F_SETLK

bir kilit Edinme veya kilidi açmak (l_type, F_UNLCK olduğunda) l_whence, l_start ve l_len kilit alanları tarafından belirtilen baytlarda. Çakışan bir kilit tarafından başka bir işlem tarafından tutulursa, bu çağrı -1 değerini döndürür ve errno'yu EACCES veya EAGAIN olarak ayarlar. F_SETLK gelince

F_SETLKW

ama çakışan bir kilit dosyası üzerinde tutulması halinde bu kilit serbest olması için bekletin.Bir sinyal beklerken yakalanırsa, çağrı kesilir ve ( sinyal ileticisi geri döndükten sonra) hemen geri döner (-1 değerini döndürür ve errnoEINTR ile ayarlanır).

+0

güzel cevap, sana adam sayfası bağlantısı artık çalışmıyor Yani PHP kaynak kodu – nulll

+0

bildirdi appriciate ama http://www.manpages.info/linux/fcntl.2.html muhtemelen aynı içeriğidir. Ancak, "Çekirdek 2.0'den beri, sürünün (2) ve fcntl (2) tarafından yerleştirilen kilit türleri arasında hiçbir etkileşim yoktur," diye soruyor, bu yüzden hala alakalı olup olmadığını merak ediyorum. –