gpt4 book ai didi

c - 鉴于我打开了一个文件,有没有办法确定其他进程是否也打开了该文件

转载 作者:行者123 更新时间:2023-12-03 10:44:57 25 4
gpt4 key购买 nike

我有一个文件描述符(使用 open(2) 获得)。在某个时间点,我可以确定该文件已取消链接(fstat(2),检查 st_nlinks)。但是,在我可以关闭我的文件描述符之前,我想验证没有其他进程仍然打开该文件(至少用于写入)。

inotify 可以(并且确实)给我一些不错的事件来工作,例如,当 st_nlinks 更改时,IN_ATTRIB,当另一个进程关闭文件时(并打开文件进行写入,这并不意味着没有人仍然有它打开以供写入)。

基本上我正在跟踪一个日志文件,并且需要确保我得到所有已写入的信息,即使在重命名之后,但是一旦文件被重命名和/或删除, 所有编写器都已关闭,我没有必要继续打开我的文件描述符。

(避免竞争 w.r.t. 打开文件并确保 inotify 描述符引用同一个文件超出了这个问题的范围。)

最佳答案

不是万无一失,但如果你可以使用 inotify 跟踪重命名应该“足够好”,显然有一些竞争条件(按照处理任何 inotify 时的标准)。对此进行改进需要对从/proc 引用的每个未删除文件进行 stat(),并且在我看来并不能有效地改进解决方案。

第一步,给定一个 pid 和 fd(作为字符串,因为这是我们从 readdir(3) 获取它们的方式),获取它打开的模式:

static
int getflags(const char* pidn, const char* fdn)
{
char fnamebfr[525];
char bfr[1 << 13];
sprintf(fnamebfr, "/proc/%s/fdinfo/%s", pidn, fdn);
int fd = open(fnamebfr, O_RDONLY);
if (fd < 0) {
if (errno != ENOENT)
perror(fnamebfr);
return 0;
}
int r = read(fd, bfr, sizeof(bfr));
if (r < 0) {
perror(fnamebfr);
r = 0;
} else if (r == sizeof(bfr)) {
r = 0;
fprintf(stderr, "bfr in %s is too small.\n", __FUNCTION__);
} else {
bfr[r] = 0;
r = 0;
char *fb = strstr(bfr, flagsstr);
if (!fb) {
fprintf(stderr, "Error locating '%s' in %s, content:\n%s\n", flagsstr, fnamebfr, bfr);
} else {
char *nptr;
fb += strlen(flagsstr);
r = strtol(fb, &nptr, 8);
if (*nptr != '\n')
fprintf(stderr, "Parse warning for strtol, endp=\n%s\nbfr=%s\n", nptr, bfr);
}
}

close(fd);

return r;
}

注意:如果文件在执行/proc//fd/ 之间关闭,我们将在此处返回 0 (O_RDONLY),如果文件描述符被重新使用...那么我们将完全返回错误的标志。

现在我们可以走/proc/在这些标志中寻找 O_WRONLY 或 O_RDWR:

static int fileopenforwrite(const char* path)
{
size_t tlen = strlen(path);
DIR *proc, *fd;
struct dirent *procent, *fdent;
int _fd;
proc = opendir("/proc");

if (!proc) {
perror("/proc");
return -1;
}

while ((procent = readdir(proc))) {
char *endptr;
char fdpath[MAXNAMLEN + 10];

strtol(procent->d_name, &endptr, 10);
if (*endptr)
continue; /* not a pid */
sprintf(fdpath, "/proc/%s/fd", procent->d_name);
_fd = open(fdpath, O_RDONLY);
if (_fd < 0) {
if (errno != ENOENT) /* process terminated + waited */
perror(fdpath);
fd = fdopendir(_fd);
if (!fd) {
perror(fdpath);
close(_fd);
continue;
}
while ((fdent = readdir(fd))) {
if (fdent->d_type == DT_DIR)
continue; /* skip . and .. */
char readbuf[MAXNAMLEN + 11];
ssize_t r = readlinkat(_fd, fdent->d_name, readbuf, sizeof(readbuf));
if (r < 0) {
perror(fdpath);
} else if (r >= (int)sizeof(readbuf)) {
fprintf(stderr, "Bufferoverflow in %s (%s).", __FUNCTION__, __FILE__);
} else {
readbuf[r] = 0;
if (strncmp(path, readbuf, tlen) == 0 &&
(!readbuf[tlen] || strcmp(" (deleted)", readbuf + tlen) == 0))
{
/* We have an FD to the file, now we want to know if it's
* open for writing */
int f = getflags(procent->d_name, fdent->d_name);
if (f & (O_RDONLY | O_RDWR)) {
closedir(fd);
closedir(proc);
return 0;
}
}
}
}
closedir(fd); /* implicitly closes _fd */
}
}
closedir(proc);

return 1;
}

这将返回 0 表示是,1 表示错误,-1 表示无法打开/proc。

如果你使用它,显然要根据你的要求清理它。

关于c - 鉴于我打开了一个文件,有没有办法确定其他进程是否也打开了该文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59637280/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com