gpt4 book ai didi

c - dup 系统调用说明

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:17:52 30 4
gpt4 key购买 nike

  close(fileno(stdout));

int fd = dup(fileno(stdin));
//printf("Hello World\n");
write(fd, "Hello", 7);

此处 printf 和 write 都在向屏幕写入 Hello。但我认为它们不应该,因为我正在将 stdin 复制到 1 或 stdout 之前关闭。并且 printf 连接到 stdout 但不是 stdin 但它们仍在打印......如果我在理解 dup

最佳答案

由于历史习惯,您代码中的 printfwrite 恰好可以工作。这是正在发生的事情:

当用户在类 Unix 系统上登录终端,或在 X11 下打开终端窗口时,文件描述符 0、1 和 2 连接到终端设备,它们中的每一个都为 打开阅读和写作。情况就是这样,尽管通常只从 fd 0 读取并写入 fd 1 和 2

然而这里是来自 7th edition init.c 的代码:

open(tty, 2);
dup(0);
dup(0);
...
execl(getty, minus, tty, (char *)0);

下面是 ssh 是如何做到的:

ioctl(*ttyfd, TCSETCTTY, NULL);
fd = open("/dev/tty", O_RDWR);
if (fd < 0)
error("%.100s: %.100s", tty, strerror(errno));
close(*ttyfd);
*ttyfd = fd;
...
/* Redirect stdin/stdout/stderr from the pseudo tty. */
if (dup2(ttyfd, 0) < 0)
error("dup2 stdin: %s", strerror(errno));
if (dup2(ttyfd, 1) < 0)
error("dup2 stdout: %s", strerror(errno));
if (dup2(ttyfd, 2) < 0)
error("dup2 stderr: %s", strerror(errno));

(dup2 函数将 arg1 复制到 arg2,必要时先关闭 arg2。)

下面是 xterm 是如何做到的:

if ((ttyfd = open(ttydev, O_RDWR)) >= 0) {
/* make /dev/tty work */
ioctl(ttyfd, TCSETCTTY, 0);
...
/* this is the time to go and set up stdin, out, and err
*/
{
/* dup the tty */
for (i = 0; i <= 2; i++)
if (i != ttyfd) {
IGNORE_RC(close(i));
IGNORE_RC(dup(ttyfd));
}
/* and close the tty */
if (ttyfd > 2)
close_fd(ttyfd);

回到你的代码。

close(fileno(stdout));

这将关闭 fd 1。

int fd = dup(fileno(stdin));

这会将 fd 0 复制到最低的可用 fd,即 1,并将 1 分配给 fd。 (当然,这假设 fd 0 是打开的。)fd 的 0 和 1 现在都打开以进行读写(假设它们已连接到终端设备)。在 Linux 系统上,您可以验证这一点:

$ cat /proc/self/fdinfo/0
pos: 0
flags: 0100002
mnt_id: 20
$ cat /proc/self/fdinfo/1
pos: 0
flags: 0100002
mnt_id: 20

flags中的2,即常量O_RDWR,表示打开读写。

printf("Hello World\n");

这将写入 fd 1,它再次打开以读取和写入您的终端。

write(fd, "Hello", 7);

这将再次写入 fd 1。 (不过请注意,"Hello" 只有 6 个字节。)

关于c - dup 系统调用说明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32045463/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com