Файловые блокировки для Linux - PullRequest
9 голосов
/ 31 мая 2011

Я пытался использовать временные файлы:

char *temp = tempnam(NULL, "myapp_");
printf("Tempname: %s", temp)     // Prints /tmp/myapp_random
while (1) { }

Но когда я проверяю /tmp (пока приложение еще запущено), myapp_random не появляется!

Что касается использования блокировок файлов, я не могу понять это, я попытался взглянуть на <fcntl.h>, но, похоже, он сосредоточен на блокировках в определенных частях файла. Я просто хочу использовать файл целиком как блокировку (именно поэтому я предпочитаю использовать временный файл).

Есть идеи?

1 Ответ

12 голосов
/ 31 мая 2011

tempnam не создает файл, он просто дает вам имя файла, которого не было на момент его вызова.

Вам все еще нужно создайте файл самостоятельно и, следовательно, сохраняете условие гонки, в которое другой процесс может проникнуть и создать его перед вами.

На самом деле вы не хотите использовать tempnam с тех порэто даст каждому процессу свое собственное имя файла, и они смогут работать одновременно.Вам нужно фиксированное имя файла (например, /tmp/myapp.lck), которое каждый процесс открывает, а затем пытается flock.

Вам лучше с flock дляфайл блокировки, fcntl даст вам более тонкую блокировку (части файлов), но это не является обязательным требованием.

Код будет работать примерно так:

if ((mylockfd = open ("/tmp/myapp.lck", O_CREAT | O_RDWR, 0666)) < 0) {
    // error, couldn't open it.
    return;
}
if (flock (mylockfd, LOCK_EX | LOCK_NB) < 0) {
    // error, couldn't exclusive-lock it.
    return;
}
:
// Weave your magic here.
:
flock (mylockfd, LOCK_UN);

Это, вероятно, требует некоторой работы, но должно быть хорошим началом.Более обобщенное решение будет выглядеть примерно так:

int acquireLock (char *fileSpec) {
    int lockFd;

    if ((lockFd = open (fileSpec, O_CREAT | O_RDWR, 0666))  < 0)
        return -1;

    if (flock (mylockfd, LOCK_EX | LOCK_NB) < 0) {
        close (lockFd);
        return -1;
    }

    return lockFd;
}

void releaseLock (int lockFd) {
    flock (lockFd, LOCK_UN);
    close (lockFd);
}

// Calling code here.

int fd;
if ((fd = acquireLock ("/tmp/myapp.lck")) < 0) {
    fprintf (stderr, "Cannot get lock file.\n");
    return 1;
}

// Weave your magic here.

releaseLock (fd);
...