枫露清愁 发表于 2015-06-23 20:48

stdin、stdout、stderr什么时候被重定位的?

最近看内核源码,产生了一个疑问:
stdin、stdout、stderr到底对应哪个终端设备?什么时候指定的?

找了一下资料,有这样的解释:
static int noinline init_post(void)
{
    &n bsp;
    ……
    ……
    if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
      printk(KERN_WARNING "Warning: unable to open an initial co nsole.\n");
      
    (void) sys_dup(0);
    (void) sys_dup(0);
    ……
    ……
    run_init_process(XXXX);
}
在上面这个函数里,sys_open时因为还没有打开任何文件,所以此时用的是文件描述符0,通过sys_dup让stdout、stderr也对应到/dev/console。

上面的解释暂且可以认为系统启动时stdin、stdout、stderr对应到/dev/console,但以后没打开一个终端,stdin、stdout、stderr就会改变啊。用一个小的测试程序测试:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{      
    int ret;
    char *ttyname0,*ttyname1,*ttyname2;
   
    ttyname0 = ttyname(0);
    ttyname1 = ttyname(1);
    ttyname2 = ttyname(2);
   
    printf("file0 : %s\n",ttyname0);
    printf("file1 : %s\n",ttyname1);
    printf("file2 : %s\n",ttyname2);
   
    return 0;
}
我用telnet连接Linux时,在telnet的终端运行,输出的是:
file0 : /dev/pts/1
file1 : /dev/pts/1
file2 : /dev/pts/1
因为是在伪终端执行的程序,所以会输出这个结果。

我的问题是,什么时候stdin、stdout、stderr被重定位到/dev/pts/1的,对应内核哪一部分代码?
求大神指点一下,告诉是哪部分代码,自己分析也行。感激不尽


枫露清愁 发表于 2015-06-24 08:50

求高人啊!!

枫露清愁 发表于 2015-06-24 08:50

求高人啊!!

firocu 发表于 2015-06-24 10:17

本帖最后由 firocu 于 2015-06-24 10:24 编辑

个人观点:-)
我看了下代码, 子进程的标准输入输出初始化, 应该是clone的时候做得, 继承自父进程.
_do_fork-> copy_process->copy_files

之于什么时候终端变成/dev/pts, 这可能和系统初始化的进程有关, 比如systemd这些.
我记得好像用到getty这个工具了.

回复 1# 枫露清愁


   

枫露清愁 发表于 2015-06-24 14:15

回复 4# firocu
非常谢谢仁兄的回答,我去看下相关源码

   

枫露清愁 发表于 2015-06-24 17:15

看了一下getty的源码(busybox-1.23.0):
int getty_main(int argc UNUSED_PARAM, char **argv)
            /* Open the tty as standard input, if it is not "-" */
        debug("calling open_tty\n");
        open_tty();
        ndelay_off(STDIN_FILENO);
        debug("duping\n");
        xdup2(STDIN_FILENO, 1);
        xdup2(STDIN_FILENO, 2);

static void open_tty(void)
{
        /* Set up new standard input, unless we are given an already opened port */
        if (NOT_LONE_DASH(G.tty_name)) {
                if (G.tty_name != '/')
                        G.tty_name = xasprintf("/dev/%s", G.tty_name); /* will leak it */

                /* Open the tty as standard input */
                debug("open(2)\n");
                close(0);
                xopen(G.tty_name, O_RDWR | O_NONBLOCK); /* uses fd 0 */

                /* Set proper protections and ownership */
                fchown(0, 0, 0);      /* 0:0 */
                fchmod(0, 0620);      /* crw--w---- */
        } else {
                char *n;
                /*
               * Standard input should already be connected to an open port.
               * Make sure it is open for read/write.
               */
                if ((fcntl(0, F_GETFL) & (O_RDWR|O_RDONLY|O_WRONLY)) != O_RDWR)
                        bb_error_msg_and_die("stdin is not open for read/write");

                /* Try to get real tty name instead of "-" */
                n = xmalloc_ttyname(0);
                if (n)
                        G.tty_name = n;
        }
        applet_name = xasprintf("getty: %s", skip_dev_pfx(G.tty_name));
}
结合调试的结果看,当打开一个终端时,会生成一个bash进程,猜想它去创建/dev/pts/1这些节点,然后这个节点设为当前终端,接着会调用getty,根据上面的代码,重定位stdin、stdout、stderr。
但是,并没有在bash的源码里看到明确的代码,也不知道理解的对不对。还有,这些创建节点具体对应哪些源码还是不清楚,再次呼叫大神!!!

firocu 发表于 2015-06-24 19:21

本帖最后由 firocu 于 2015-06-24 19:39 编辑


我不知道你为什么这么执着于, 找到这个代码, 很多时候, 这都是大海捞针.



回复 6# 枫露清愁


   

枫露清愁 发表于 2015-06-24 19:59

对,pts是gnome-terminal生成的(CentOS6.4),谢谢仁兄。其实没啥原因,就是钻里面出不来了{:qq22:}

nswcfd 发表于 2015-06-24 21:17

钻研精神,赞一个!

bash里不会有创建pts的代码,虚拟终端是从窗口程序继承过来的。

枫露清愁 发表于 2015-06-25 08:45

回复 9# nswcfd
对滴

   
页: [1]
查看完整版本: stdin、stdout、stderr什么时候被重定位的?