stdio 是否将文件描述符偏移量设置回文件关闭时的下一个未读位置?
Does stdio set file descriptor offset back to next unread position on file closing?
根据 Linux 程序员手册,调用 fork
后,parent 和 child 进程共享打开的文件描述符和文件偏移量。
另一方面,众所周知,glibc 的 stdio 实现了缓冲。因此,调用 scanf
可能导致文件偏移量(读取)比返回给最终用户的字节数更远,剩余数据将存储在缓冲区中以供下一次调用。
但是当我执行以下操作时会发生什么:
- 呼叫
fork
。现在 parent 和 child 分享 stdin
.
- 在child进程调用
scanf
。默认情况下 stdin
是块缓冲,因此 scanf
读取块。
- 检查 child 中的文件偏移量。
- 退出 child 进程。
- 在 parent 进程中等待 child 进程。
- 检查
stdin
在 parent 中的文件偏移量。
根据glibc manual,当main
returns,
all opened streams are closed properly.
关闭时
any buffered input is discarded
所以我希望 parent 的 stdin
文件偏移量位于 child 的 scanf
停止读取(真正停止读取)的位置。但是我得到 parent 的 stdin
文件偏移量移回了返回给用户的输入结束位置。
我通过手册和互联网进行了搜索,但没有找到任何描述此行为的信息。指定了吗?
这是我的代码:
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
int main() {
int fd = fileno(stdin);
printf("Begin pos: %ld\n", lseek(fd, 0, SEEK_CUR));
pid_t pid = fork();
if (pid == 0) {
char buffer[4096] = {};
int readed = scanf("%s", buffer);
printf("Child readed: %d, pos: %ld\n", readed, lseek(fd, 0, SEEK_CUR));
return 0;
}
int status = 0;
wait(&status);
printf("Parent pos: %ld\n", lseek(fd, 0, SEEK_CUR));
return 0;
}
这是输出:
> echo "aaa bbb ccc" > test
> ./a.out < test
Begin pos: 0
Child readed: 1, pos: 12
Parent pos: 3
观察到的行为符合 fclose
函数的 POSIX 要求:
If the file is not already at EOF, and the file is one capable of seeking, the file offset of the underlying open file description shall be set to the file position of the stream if the stream is the active handle to the underlying file description.
根据 Linux 程序员手册,调用 fork
后,parent 和 child 进程共享打开的文件描述符和文件偏移量。
另一方面,众所周知,glibc 的 stdio 实现了缓冲。因此,调用 scanf
可能导致文件偏移量(读取)比返回给最终用户的字节数更远,剩余数据将存储在缓冲区中以供下一次调用。
但是当我执行以下操作时会发生什么:
- 呼叫
fork
。现在 parent 和 child 分享stdin
. - 在child进程调用
scanf
。默认情况下stdin
是块缓冲,因此scanf
读取块。 - 检查 child 中的文件偏移量。
- 退出 child 进程。
- 在 parent 进程中等待 child 进程。
- 检查
stdin
在 parent 中的文件偏移量。
根据glibc manual,当main
returns,
all opened streams are closed properly.
关闭时
any buffered input is discarded
所以我希望 parent 的 stdin
文件偏移量位于 child 的 scanf
停止读取(真正停止读取)的位置。但是我得到 parent 的 stdin
文件偏移量移回了返回给用户的输入结束位置。
我通过手册和互联网进行了搜索,但没有找到任何描述此行为的信息。指定了吗?
这是我的代码:
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
int main() {
int fd = fileno(stdin);
printf("Begin pos: %ld\n", lseek(fd, 0, SEEK_CUR));
pid_t pid = fork();
if (pid == 0) {
char buffer[4096] = {};
int readed = scanf("%s", buffer);
printf("Child readed: %d, pos: %ld\n", readed, lseek(fd, 0, SEEK_CUR));
return 0;
}
int status = 0;
wait(&status);
printf("Parent pos: %ld\n", lseek(fd, 0, SEEK_CUR));
return 0;
}
这是输出:
> echo "aaa bbb ccc" > test
> ./a.out < test
Begin pos: 0
Child readed: 1, pos: 12
Parent pos: 3
观察到的行为符合 fclose
函数的 POSIX 要求:
If the file is not already at EOF, and the file is one capable of seeking, the file offset of the underlying open file description shall be set to the file position of the stream if the stream is the active handle to the underlying file description.