我是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时,它不会自动刷新?
@Edit:
对不起,我的错误,我找到了原因,在我的初步计划中:
close(fd_dup);
但没有:
fclose(f_dup);
使用fclose(f_dup);
替换close(f_dup);
后,它可以正常工作。
因此,如果以适当的方式关闭,重复的fd会自动刷新write()
&amp; close()
是一对,fwrite()
&amp; fclose()
是一对,不应混用它们。
实际上,在代码中我可以直接使用重复的fd_dup与write()
&amp; 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);
}
答案 0 :(得分:2)
来自dup
手册页:
从这些系统调用之一成功返回后,旧文件描述符和新文件描述符可以互换使用。它们引用相同的打开文件描述(参见open(2)),从而共享文件偏移量和文件状态标志;例如,如果通过在其中一个描述符上使用lseek(2)修改文件偏移量,则另一个描述符的偏移量也会更改。
这意味着当您写入重复的文件描述符时会更改搜索指针,因此,在写入复制后从第一个文件描述符读取不应读取任何数据。
您正在使用fdopen
创建重复流的分离的seek_ptr和end_ptr,这样,fd_dup
就会停止重复。这就是为什么你可以在刷新和关闭流后读取数据。
如果你不刷新第二个文件描述符,我找不到任何有关你无法阅读的强有力的事实。我可以补充一点,它可能与sync
系统调用有关。
毕竟,如果你需要一个IO缓冲区,你可能会使用错误的机制,检查命名管道和其他缓冲操作系统机制。
答案 1 :(得分:1)
我无法理解你的问题。我在Microsoft VC2008下测试了它(必须用io.h替换unistd.h)和gcc 4.2.1。
我注释掉了fflush(f_dup)
,因为它在关闭之前没有用close(fd_dup);
,因为文件描述符已经关闭了,所以这段代码现在看起来像:
// 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);
它运作正常。我上了两个系统:
original file descriptor: 3
duplicated file descriptor: 4
hello