После директив #include и объявлений откройте дескриптор файла.
#include
#include
#include
#include
const char *test_file = "/tmp/test_lock";
int main() {
int file_desc;
struct flock region_to_lock;
int res;
file_desc = open(test_file, O_RDWR | O_CREAT, 0666);
if (!file_desc) {
fprintf(stderr, "Unable to open %s for read/write\n", test_file);
exit(EXIT_FAILURE);
}
В оставшейся части программы задаются разные участки файла, и делается попытка установить для них блокировки разных типов:
region_to_lock.l_type = F_RDLCK;
region_to_lock.l_whence = SEEK_SET;
region_to_lock.l_start = 10;
region_to_lock.l_len = 5;
printf("Process %d, trying F_RDLCK, region %d to %d\n", getpid(), (int)region_to_lock.l_start,
(int)(region_to_lock.l_start + region_to_lock.l_len));
res = fcntl(file_desc, F_SETLK, ®ion_to_lock);
if (res == -1) {
printf("Process %d - failed to lock region\n", getpid());
} else {
printf("Process %d — obtained lock region\n", getpid());
}
region_to_lock.l_type = F_UNLCK;
region_to_lock.l_whence = SEEK_SET;
region_to_lock.l_start = 10;
region_to_lock.l_len = 5;
printf("Process %d, trying F_UNLCK, region %d to %d\n", getpid(), (int)region_to_lock.l_start,
(int)(region_to_lock.l_start + region_to_lock.l_len));
res = fcntl(file_desc, F_SETLK, ®ion_to_lock);
if (res == -1) {
printf("Process %d — failed to unlock region\n", getpid());
} else {
printf("Process %d — unlocked region\n", getpid());
}
region_to_lock.l_type = F_UNLCK;
region_to_lock.l_whence = SEEK_SET;
region_to_lock.l_start = 0;
region_to_lock.l_len = 50;
printf("Process %d, trying F_UNLCK, region %d to %d\n", getpid()", (int)region_to_lock.l_start,
(int)(region_to_lock.l_start + region_to_lock.l_len));
res = fcntl(file_desc, F_SETLK, ®ion_to_lock);
if (res == -1) {
printf("Process %d — failed to unlock region\n", getpid());
} else {
printf("Process %d — unlocked region\n", getpid());
}
region_to_lock.l_type = F_WRLCK;
region_to_lock.l_whence = SEEK_SET;
region_to_lock.lstart = 16;
region_to_lock.l_len = 5;
printf("Process %d, trying F_WRLCK, region %d to %d\n", getpid(), (int)region_to_lock.l_start,
(int)(region_to_lock.l_start + region_to_lock.l_len));
res = fcntl(file_desc, F_SETLK, ®ion_to_lock);
if (res == -1) {
printf("Process %d — failed to lock region\n", getpid());
} else {
printf("Process %d — obtained lock on region\n", getpid());
}
region_to_lock.l_type = F_RDLCK;
region_to_lock.l_whence = SEEK_SET;
region_to_lock.l_start = 40;
region_to_lock.l_len = 10;
printf("Process %d, trying F_RDLCK, region %d to %d\n", getpid(), (int)region_to_lock.l_start,
(int)(region_to_lock.l_start + region_to_lock.l_len));
res = fcntl(filedesc, F_SETLK, ®ion_to_lock);
if (res == -1) {
printf("Process %d — failed to lock region\n", getpid());
} else {
printf("Process %d — obtained lock on region\n", getpid());
}
region_to_lock.l_type = F_WRLCK;
region_to_lock.l_whence = SEEK_SET;
region_to_lock.l_start = 16;
region_to_lock. l_len = 5;
printf("Process %d, trying F_WRLCK with wait, region %d to %d\n", getpid(), (int)region_to_lock.l_start,
(int)(region_to_lock.l_start + region_to_lock.l_len));
res = fcntl(file_desc, F_SETLKW, ®ion_to_lock);
if (res == -1) {
printf("Process %d — failed to lock region\n", getpid());
} else {
printf("Process %d — obtained lock, on region\n", getpid());
}
printf ("Process %d ending\n", getpid());
close(file_desc);
exit(EXIT_SUCCESS);
}
Если вы сначала запустите программу lock3 в фоновом режиме, далее сразу запускайте новую программу:
$ . /lock3 &
$ process 227 locking file
$ ./lock5
Вы получите следующий вывод:
Process 227 locking file
Process 228, trying F_RDLCK, region 10 to 15
Process 228 — obtained lock on region
Process 228, trying F_UNLCK, region 10 to 15
Process 228 — unlocked region
Process 228, trying F_UNLCK, region 0 to 50
Process 228 — unlocked region
Process 228, trying F_WRLCK, region 16 to 21
Process 228 — failed to lock on region
Process 228, trying F_RDLCK, region 4 0 to 50
Process 228 - failed to lock on region
Process 228, trying F_WRLCK with wait, region 16 to 21
Process 227 closing file
Process 228 — obtained lock on region
Process 228 ending
Как это работает
Сначала программа пытается заблокировать участок с 10-го по 15-й байты с помощью разделяемой блокировки. Эта область уже заблокирована блокировкой того же типа, но одновременные разделяемые блокировки допустимы, и установка блокировки завершается успешно.
Затем программа снимает свою разделяемую блокировку с участка файла, и эта операция тоже завершается успешно. Далее она пытается разблокировать первые 50 байтов файла, даже если у них нет никакой блокировки. Это действие тоже завершается успешно, потому что, несмотря на то, что программа не установила блокировок на этот участок, конечный результат запроса на снятие блокировки заключается в констатации того, что для первых 50 байтов данная программа не поддерживает никаких блокировок.
Читать дальше