我有一个链接列表与fd和我用来打开每个条目中的文件的string。 我想打开并添加文件到这个列表只有当这个文件还没有打开,因为我打开并parsing这个文件,不想做两次。 我的想法是将文件名与此列表中的每个名称进行比较,但是我的程序多次执行此操作,Linux中的一个文件可能有多个名称(软/硬链接)。 我认为它不应该是那么复杂,因为它容易的操作系统来检查,是否我已经使用inode或不,r? 我已经试图open同一个文件,但没有flock ,但我总是得到一个新的fd 。
如何在不提取整个文件的情况下更改存档(.ear)文件内的文件
什么是检测文件是否在Windows中打开的编程方式?
Perl – 如何从分隔的txt文件读取每一行并处理它
当你成功的打开一个文件时,在文件上使用fstat 。 检查由fstat提交的struct stat的st_ino和st_dev是否已经记录在链表中。 如果是,则关闭文件描述符并转到下一个文件。 否则,将文件描述符,文件名和st_ino和st_dev值添加到列表中。
在打开文件之前,您可以使用stat来检查,但如果通常的情况是该文件尚未打开,则使用fstat会稍快。
在这种情况下,考虑数据结构通常是有用的。 更改为不允许重复的数据结构,例如哈希表。
维护一组您之前见过的数据。 我为这个集合使用了一个哈希表 。 根据@ RossRidge的回答 ,使用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",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: %dn",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
只要你不关闭成功和有意打开的文件,你可以使用非阻塞的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 %sn",fn); return fd; }else{ fprintf(stderr,"Failed to open or lock %sn",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
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。