我有一个带有fd和字符串的链表我用来在每个条目中打开这个文件。我想打开并仅在此文件尚未打开的情况下将文件添加到此列表中,因为我打开并解析此文件并且不想两次执行此操作。我的想法是将文件名与此列表中的每个名称进行比较,但我的程序多次执行,Linux中的一个文件可以有多个名称(软/硬链接)。我认为它不应该那么复杂,因为操作系统很容易检查,我是否已经使用了inode,r?
我已经尝试open
使用flock
和不使用fd
的同一个文件,但我总是得到一个新的$("li.menuContainer > a.top").click(function(e) {
e.preventDefault();
$div = $(this).next("div.sub");
$("li.menuContainer div.sub").not($div).slideUp();
$div.slideDown();
});
。
答案 0 :(得分:7)
成功打开文件后,请在文件中使用fstat
。检查st_ino
提交的st_dev
的{{1}}和fstat
是否已记录在您的链接列表中。如果是,则关闭文件描述符并继续下一个文件。否则,将文件描述符,文件名以及st_ino
和st_dev
值添加到列表中。
您可以在打开文件之前使用struct stat
进行检查,但如果通常情况下该文件尚未打开,则使用fstat
后会稍快一些。
答案 1 :(得分:1)
在这种情况下,考虑您的数据结构通常很有用。更改为不允许重复的数据结构,例如哈希表。
维护一组您之前见过的数据。我为这套使用了hash table。根据{{3}},使用inode和设备作为密钥。这允许在O(1)时间内发现重复。
以下是一个示例实现。
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <glib.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
static int get_fd(GHashTable *fds, const char *filename, int mode) {
int fd;
struct stat stat;
int keysize = 33;
char key[keysize]; /* Two 64 bit numbers as hex and a separator */
/* Resolve any symlinks */
char *real_filename = realpath(filename, NULL);
if( real_filename == NULL ) {
printf("%s could not be resolved.\n", filename);
return -1;
}
/* Open and stat */
fd = open( real_filename, mode );
if( fd < 0 ) {
printf("Could not open %s: %s.\n", real_filename, strerror(errno));
return -1;
}
if( fstat(fd, &stat) != 0 ) {
printf("Could not stat %s: %s.\n", real_filename, strerror(errno));
return -1;
}
/* Make a key for tracking which data we've processed.
This uses both the inode and the device it's on.
It could be done more efficiently as a bit field.
*/
snprintf(key, keysize, "%lx|%lx", (long int)stat.st_ino, (long int)stat.st_dev);
/* See if we've already processed that */
if( g_hash_table_contains(fds, key) ) {
return 0;
}
else {
/* Note that we've processed it */
g_hash_table_add(fds, key);
return fd;
}
}
int main(int argc, char** argv) {
int mode = O_RDONLY;
int fd;
GHashTable *fds = g_hash_table_new(&g_str_hash, &g_str_equal);
for(int i = 1; i < argc; i++) {
char *filename = argv[i];
fd = get_fd(fds, filename, mode);
if( fd == 0 ) {
printf("%s has already been processed.\n", filename);
}
else if( fd < 0 ) {
printf("%s could not be processed.\n", filename);
}
else {
printf("%s: %d\n", filename, fd);
}
}
}
这是一个示例结果。
$ touch one two three
$ ln one one_link
$ ln -s two two_sym
$ ./test one* two* three*
one: 3
one_link has already been processed.
two: 5
two_sym has already been processed.
three: 7
答案 2 :(得分:-1)
只要您不关闭成功和有意打开的文件,就可以使用非阻止flock
来阻止对同一文件的另一次锁定:
#include <unistd.h>
#include <sys/file.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <assert.h>
int openAndLock(const char* fn){
int fd = -1;
if(((fd = open(fn, O_RDONLY)) >= 0) && (flock(fd, LOCK_EX|LOCK_NB) == 0)){
fprintf(stderr, "Successfully opened and locked %s\n", fn);
return fd;
}else{
fprintf(stderr, "Failed to open or lock %s\n", fn);
close(fd);
return -1;
}
}
int main(int argc, char** argv){
for(int i=1; i<argc; i++){
openAndLock(argv[i]);
}
return 0;
}
示例:
$ touch foo
$ ln foo bar
$ ./a.out foo foo
Successfully opened and locked foo
Failed to open or lock foo
$ ./a.out foo bar
Successfully opened and locked foo
Failed to open or lock bar