【发布时间】:2014-11-03 13:20:36
【问题描述】:
我是C初学者,尝试使用dup(),我写了一个程序来测试这个功能,结果和我预期的有点不同。
代码:
// unistd.h, dup() test
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
extern void dup_test();
int main() {
dup_test();
}
// dup()test
void dup_test() {
// open a file
FILE *f = fopen("/tmp/a.txt", "w+");
int fd = fileno(f);
printf("original file descriptor:\t%d\n",fd);
// duplicate file descriptor of an opened file,
int fd_dup = dup(fd);
printf("duplicated file descriptor:\t%d\n",fd_dup);
FILE *f_dup = fdopen(fd_dup, "w+");
// write to file, use the duplicated file descriptor,
fputs("hello\n", f_dup);
fflush(f_dup);
// close duplicated file descriptor,
fclose(f_dup);
close(fd_dup);
// allocate memory
int maxSize = 1024; // 1 kb
char *buf = malloc(maxSize);
// move to beginning of file,
rewind(f);
// read from file, use the original file descriptor,
fgets(buf, maxSize, f);
printf("%s", buf);
// close original file descriptor,
fclose(f);
// free memory
free(buf);
}
程序尝试通过复制的fd写入,然后关闭复制的fd,然后尝试通过原始fd读取。
本以为当我关闭复制的fd时,io缓存会自动刷新,但事实并非如此,如果我去掉代码中的fflush()函数,原来的fd将无法读取写入的内容由已经关闭的重复fd。
我的问题是:
这是否意味着当关闭重复的 fd 时,它不会自动刷新?
@编辑:
对不起,我的错误,我找到了原因,在我最初的程序中有:
close(fd_dup);
但没有:
fclose(f_dup);
使用fclose(f_dup); 替换close(f_dup); 后,它可以工作了。
所以,如果以正确的方式关闭,重复的 fd 会自动刷新,write() 和 close() 是一对,fwrite() 和 fclose() 是一对,不应该混合它们。
实际上,在代码中我可以直接将复制的 fd_dup 与write() 和close() 一起使用,根本不需要创建新的FILE。
所以,代码可以是:
// unistd.h, dup() test
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#define BUF_SIZE 1024 // 1 kb
extern void dup_test();
int main() {
dup_test();
}
// dup()test
void dup_test() {
// open a file
FILE *f = fopen("/tmp/a.txt", "w+");
int fd = fileno(f);
printf("original file descriptor:\t%d\n",fd);
// duplicate file descriptor of an opened file,
int fd_dup = dup(fd);
printf("duplicated file descriptor:\t%d\n",fd_dup);
// write to file, use the duplicated file descriptor,
write(fd_dup, "hello\n", BUF_SIZE);
// close duplicated file descriptor,
close(fd_dup);
// allocate memory
char *buf = malloc(BUF_SIZE);
// move to beginning of file,
rewind(f);
// read from file, use the original file descriptor,
fgets(buf, BUF_SIZE, f);
printf("%s", buf);
// close original file descriptor,
fclose(f);
// free memory
free(buf);
}
【问题讨论】:
-
你可能想
strace你的程序来检查它实际上做了什么系统调用。在我的系统上,你的程序总是打印hello。我认为可能发生的事情是f_dup被刷新,但f在此之前查看您的文件(fopen)。 -
既然你有
fdopen你的fd,那么你应该主要操作的对象是FILE*。它们本质上是相同的东西,不要两次关闭相同的东西。而且,您对FILE*和int有点困惑,这意味着fd。FILE *是文件流,它是标准表示,因此它是跨平台的。fd其实就是int,一个文件描述符表的索引号,是*nix系统的特性。 -
@zch 谢谢,strace 是一个很棒的工具!