关于dup系统调用的说明

时间:2015-08-17 08:07:05

标签: c linux unix

  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相关联,但仍然正在打印...请说明我在理解复制时是否有任何错误

2 个答案:

答案 0 :(得分:4)

如果您在终端上运行程序,则stdinstdout会打开同一个文件 - 您的终端设备。因此,写入stdin - 或dup() fileno(stdin) - 写入您的终端设备并且您看到它就不足为奇了。

如果您运行程序时将stdin连接到其他位置(如磁盘文件),您会看到不同的结果:

./program < file

答案 1 :(得分:4)

由于历史习惯,代码中的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

2中的flags,即常量O_RDWR,意味着可以阅读和书写。

printf("Hello World\n");

这写入fd 1,再次打开读取和写入终端。

write(fd, "Hello", 7);

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