[英]Explanation on dup syscall
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时是否有任何错误
如果在终端上运行程序,则stdin
和stdout
将打开同一文件-终端设备。 因此,写入stdin
或fileno(stdin)
的dup()
fileno(stdin)
-写入终端设备而您看到它并不奇怪。
如果在其他地方(例如磁盘文件)连接了stdin
运行程序,则会看到不同的结果:
./program < file
由于历史习惯, printf
和代码中的write
操作恰好起作用。 这是正在发生的事情:
当用户登录到类Unix系统上的终端或在X11下打开终端窗口时,文件描述符0、1和2连接到终端设备,并且每个文件描述符都打开以进行读取和写入 。 尽管实际上通常只从fd 0读取数据并写入fd 1和2的情况仍然是这种情况。
这是第7版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
为in的2
是常量O_RDWR
,表示已打开以进行读取和写入。
printf("Hello World\n");
这将写入fd 1,该fd 1再次可以读取和写入终端。
write(fd, "Hello", 7);
这将再次写入fd 1。 (但是请注意, "Hello"
只有6个字节。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.