简体   繁体   English

dup syscall的说明

[英]Explanation on dup syscall

  close(fileno(stdout));

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

Here for both printf and write is writing Hello to the screen..But I think they should not because I am duplicating the stdin to 1 or stdout closed perviously. 对于printf和write来说,都是在屏幕上写Hello。.但是我认为它们不应该这样做,因为我将stdin复制为1或stdout关闭。 And printf is connected to stdout but not stdin but still they are printing...Please explain if I have anything wrong in understanding the dup 并且printf连接到stdout而不是stdin但是它们仍然在打印...请说明我在理解dup时是否有任何错误

If you are running your program on a terminal, then stdin and stdout are opens of the same file - your terminal device. 如果在终端上运行程序,则stdinstdout将打开同一文件-终端设备。 So it should not be surprising that writing to stdin - or a dup() of fileno(stdin) - writes to your terminal device, and you see it. 因此,写入stdinfileno(stdin)dup() fileno(stdin) -写入终端设备而您看到它并不奇怪。

If you run your program with stdin connected somewhere else, like a disk file, you'll see a different result: 如果在其他地方(例如磁盘文件)连接了stdin运行程序,则会看到不同的结果:

./program < file

The printf and write in your code happen to work, due to historical custom. 由于历史习惯, printf和代码中的write操作恰好起作用。 Here's what's happening: 这是正在发生的事情:

When a user logs into a terminal on a Unix-like system, or opens a terminal window under X11, file descriptors 0, 1, and 2 are connected to a terminal device, and each of them is opened for both reading and writing . 当用户登录到类Unix系统上的终端或在X11下打开终端窗口时,文件描述符0、1和2连接到终端设备,并且每个文件描述符都打开以进行读取和写入 This is the case despite the fact that one normally only reads from fd 0 and writes to fd 1 and 2 . 尽管实际上通常只从fd 0读取数据并写入fd 1和2的情况仍然是这种情况。

Yet here is the code from 7th edition init.c : 这是第7版init.c中的代码:

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

And here is how ssh does it: 这是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));

(The dup2 function dups arg1 into arg2, closing arg2 first if necessary.) dup2函数将arg1复制到arg2中,如有必要,先关闭arg2。)

And here is how xterm does it: 这是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);

Back to your code. 回到您的代码。

close(fileno(stdout));

This closes fd 1. 关闭fd 1。

int fd = dup(fileno(stdin));

This duplicates fd 0 into the lowest available fd, which is 1, and assigns 1 to fd . 这会将fd 0复制到最低可用fd中,即1,并将1分配给fd (This assumes that fd 0 is open, of course.) Both fd's 0 and 1 are now open for reading and writing (assuming they're connected to a terminal device). (当然,假设fd 0是打开的。)fd的0和1现在都已打开以进行读取和写入(假设它们已连接到终端设备)。 On a Linux system you can verify this: 在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

The 2 in flags , which is the constant O_RDWR , means open for reading and writing. flags为in的2是常量O_RDWR ,表示已打开以进行读取和写入。

printf("Hello World\n");

This writes to fd 1, which is, once again, open for reading and writing to your terminal. 这将写入fd 1,该fd 1再次可以读取和写入终端。

write(fd, "Hello", 7);

This writes to fd 1 again. 这将再次写入fd 1。 (Note that "Hello" is only 6 bytes, though.) (但是请注意, "Hello"只有6个字节。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM