如何检查文件是否已在C中打开

时间:2013-09-06 01:05:36

标签: c linux

我正在研究一个多线程系统,根据文件访问权限,可以在不同的线程之间共享文件。如何检查文件是否已被另一个线程打开。提前致谢

4 个答案:

答案 0 :(得分:3)

您可以使用int flock(int fd, int operation);将文件标记为已锁定,并检查文件是否已锁定。

   Apply or remove an advisory lock on the open file specified by fd.
   The argument operation is one of the following:

       LOCK_SH  Place a shared lock.  More than one process may hold a
                shared lock for a given file at a given time.

       LOCK_EX  Place an exclusive lock.  Only one process may hold an
                exclusive lock for a given file at a given time.

       LOCK_UN  Remove an existing lock held by this process.
如果你在每个线程中单独打开文件,

flock应该在一个线程应用程序中工作: multiple threads able to get flock at the same time

有关flock的更多信息及其潜在的弱点here

答案 1 :(得分:2)

要查明上是否已打开命名文件,您可以扫描/proc/self/fd目录以查看该文件是否与文件描述符相关联。下面的程序草拟了一个解决方案:

DIR *d = opendir("/proc/self/fd");
if (d) {
    struct dirent *entry;
    struct dirent *result;

    entry = malloc(sizeof(struct dirent) + NAME_MAX + 1);
    result = 0;
    while (readdir_r(d, entry, &result) == 0) {
        if (result == 0) break;
        if (isdigit(result->d_name[0])) {
            char path[NAME_MAX+1];
            char buf[NAME_MAX+1];
            snprintf(path, sizeof(path), "/proc/self/fd/%s",
                     result->d_name);
            ssize_t bytes = readlink(path, buf, sizeof(buf));
            buf[bytes] = '\0';
            if (strcmp(file_of_interest, buf) == 0) break;
        }
    }
    free(entry);
    closedir(d);
    if (result) return FILE_IS_FOUND;
}
return FILE_IS_NOT_FOUND;

从您的评论中,您似乎想要检索现有的FILE *,如果之前已经通过对该文件的fopen()调用创建了FILE *。标准C库没有提供迭代所有当前打开的fileno()的机制。如果有这样的机制,您可以使用/proc/self/fd/#派生其文件描述符,然后使用readlink()查询FILE *,如上所示。

这意味着您需要使用数据结构来管理您的开放{{1}}。可能使用文件名作为键的哈希表对您来说最有用。

答案 2 :(得分:1)

我不太了解Windows上的多线程,但如果您使用的是Linux,那么您有很多选择。 Here FANTASTIC 资源。您也可以利用任何file-locking features offered inherently or explicitly by the OS(例如:fcntl)。有关Linux锁here的更多信息。创建和手动管理自己的互斥锁可以提供比原本更灵活的灵活性。 user814064关于flock()的评论看起来像是一个完美的解决方案,但是选择它绝对不会受到伤害!

添加了一个代码示例:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

FILE *fp;
int counter;
pthread_mutex_t fmutex = PTHREAD_MUTEX_INITIALIZER;

void *foo() {
        // pthread_mutex_trylock() checks if the mutex is
        // locked without blocking
        //int busy = pthread_mutex_trylock(&fmutex);

        // this blocks until the lock is released
        pthread_mutex_lock(&fmutex);
        fprintf(fp, "counter = %d\n", counter);
        printf("counter = %d\n", counter);
        counter++;
        pthread_mutex_unlock(&fmutex);
}

int main() {

        counter = 0;
        fp = fopen("threads.txt", "w");

        pthread_t thread1, thread2;

        if (pthread_create(&thread1, NULL, &foo, NULL))
                printf("Error creating thread 1");
        if (pthread_create(&thread2, NULL, &foo, NULL))
                printf("Error creating thread 2");

        pthread_join(thread1, NULL);
        pthread_join(thread2, NULL);

        fclose(fp);
        return 0;
}

答案 3 :(得分:0)

如果您倾向于在shell中执行此操作,则只需使用lsof $filename