锁定并发进程访问的文件

问题描述 投票:0回答:2

我需要使用 shell CGI 写入和读取配置文件,并且我还有一个 C 程序必须每隔几秒读取和修改配置文件。我尝试使用集群来维护数据完整性并防止竞争条件,但 CGI 和 C 程序仍然能够同时访问该文件。

如果我在文件上使用 2 个 C 程序,它可以工作,但不能同时使用 shell CGI 和 C 程序。

这是正在使用的C程序:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

int main() {
    FILE *file;
    struct flock fl = {0};
    char buff[1000];

    file = fopen("/home/siddusuhaas/sample.conf", "r+");
    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }
    printf("Opened File\n");

    // Set an exclusive lock on the entire file
    fl.l_type = F_WRLCK;
    fl.l_whence = SEEK_SET;
    fl.l_start = 0;
    fl.l_len = 0;

    if (fcntl(fileno(file), F_SETLKW, &fl) == -1) {
        perror("Error locking file");
        fclose(file);
        return 1;
    }
    printf("File Lock Successful\n");

    // Perform operations on the locked file here
    system("lslocks | grep 'bcf.conf'");

    // Read the file contents
    size_t nread = fread(buff, sizeof(char), sizeof(buff) - 1, file);
    if (nread == 0 && !feof(file)) {
        perror("Error reading file");
        fclose(file);
        return 1;
    }
    buff[nread] = '\0'; // Null-terminate the buffer
    printf("Data is %zu\t %.*s\n", nread, (int)nread, buff);
    for (int i = 0; i < 10; i++) {
        system("lslocks | grep 'bcf.conf'");
        sleep(1);
        fseek(file , 0  , SEEK_SET);
        memset(buff, 0, sizeof(buff));
        nread = fread(buff, sizeof(char), sizeof(buff) - 1, file);
        if (nread == 0 && !feof(file)) {
            perror("Error reading file");
            fclose(file);
            return 1;
        }
        buff[nread] = '\0'; // Null-terminate the buffer
        printf("Data is %zu\t %.*s\n", nread, (int)nread, buff);
    }
    fl.l_type = F_UNLCK;
    if (fcntl(fileno(file), F_SETLK, &fl) == -1) {
        perror("Error unlocking file");
        fclose(file);
        return 1;
    }
    printf("File Unlocked Successfully\n");

    fclose(file);
    return 0;
}

这是我的 CGI:

#!/bin/bash

file=/home/siddusuhaas/sample.conf

exec 200>>"$file"
if ! flock -x 200; then
    echo "Unable to acquire lock on file" 
    exit 1
fi

echo "Surprise! The file is locked!" > "$file"

#Release the lock
exec 200>&-
linux file-locking flock fcntl
2个回答
1
投票

flock(1)
程序使用
flock(2)
系统调用来锁定文件。您的 C 程序正在使用
fcntl(2)
来锁定文件。这是两种不同的锁定机制,在 Linux 上不会相互作用。更改 C 程序以也使用
flock(2)
锁。

我还会放弃使用 stdio 函数来读取和写入文件;在存在多个进程修改同一文件的情况下,stdio 缓冲与实际读写底层文件之间的交互可能是微妙且难以重现错误的根源。保持简单,只需使用

open()
/
read()
/
write()
/等等。


0
投票

要获得快速、简单且不那么脏的解决方案,不需要任何特殊工具,请使用

mkdir
。请参阅这篇文章了解一个简单的示例。

mkdir
很简单且原子 - 如果目录不存在,它会创建一个,然后返回成功,所以你知道你,并且只有你拥有锁。如果它不能这样做,它会返回一个错误,所以你知道你现在无法获得锁。

使用一点代码,您可以让它等待,直到它可以轮流,或者检查是否存在超过一定时间的锁并自动删除它,等等。这也可以让您在两者中应用相同的简单逻辑

 bash
和 C.

最后一个建议 - 在退出时设置陷阱以删除锁定文件。
您应该尽快明确地删除它,但是意外的程序退出应该尽可能地清理掉它们,锁定文件是一个典型的例子,说明为什么人们不应该在一个简单的

 时愉快地使用 
kill -9
 kill
就可以了。

© www.soinside.com 2019 - 2024. All rights reserved.