免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2540 | 回复: 9
打印 上一主题 下一主题

[文件系统] stdin、stdout、stderr什么时候被重定位的? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2015-06-23 20:48 |只看该作者 |倒序浏览
最近看内核源码,产生了一个疑问:
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的,对应内核哪一部分代码?
求大神指点一下,告诉是哪部分代码,自己分析也行。感激不尽


论坛徽章:
0
2 [报告]
发表于 2015-06-24 08:50 |只看该作者
求高人啊!!

论坛徽章:
0
3 [报告]
发表于 2015-06-24 08:50 |只看该作者
求高人啊!!

论坛徽章:
8
羊年新春福章
日期:2015-03-19 02:03:312015亚冠之北京国安
日期:2015-06-16 22:04:45程序设计版块每日发帖之星
日期:2015-06-23 22:20:00每日论坛发贴之星
日期:2015-06-23 22:20:002015亚冠之首尔
日期:2015-06-24 19:18:072015亚冠之广州恒大
日期:2015-08-06 10:29:442015亚冠之柏太阳神
日期:2015-11-02 11:21:0515-16赛季CBA联赛之辽宁
日期:2015-12-09 15:05:02
4 [报告]
发表于 2015-06-24 10:17 |只看该作者
本帖最后由 firocu 于 2015-06-24 10:24 编辑

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

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

回复 1# 枫露清愁


   

论坛徽章:
0
5 [报告]
发表于 2015-06-24 14:15 |只看该作者
回复 4# firocu
非常谢谢仁兄的回答,我去看下相关源码

   

论坛徽章:
0
6 [报告]
发表于 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[0] != '/')
                        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的源码里看到明确的代码,也不知道理解的对不对。还有,这些创建节点具体对应哪些源码还是不清楚,再次呼叫大神!!!

论坛徽章:
8
羊年新春福章
日期:2015-03-19 02:03:312015亚冠之北京国安
日期:2015-06-16 22:04:45程序设计版块每日发帖之星
日期:2015-06-23 22:20:00每日论坛发贴之星
日期:2015-06-23 22:20:002015亚冠之首尔
日期:2015-06-24 19:18:072015亚冠之广州恒大
日期:2015-08-06 10:29:442015亚冠之柏太阳神
日期:2015-11-02 11:21:0515-16赛季CBA联赛之辽宁
日期:2015-12-09 15:05:02
7 [报告]
发表于 2015-06-24 19:21 |只看该作者
本帖最后由 firocu 于 2015-06-24 19:39 编辑


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



回复 6# 枫露清愁


   

论坛徽章:
0
8 [报告]
发表于 2015-06-24 19:59 |只看该作者
对,pts是gnome-terminal生成的(CentOS6.4),谢谢仁兄。其实没啥原因,就是钻里面出不来了

论坛徽章:
20
程序设计版块每日发帖之星
日期:2015-08-17 06:20:00程序设计版块每日发帖之星
日期:2016-07-16 06:20:00程序设计版块每日发帖之星
日期:2016-07-18 06:20:00每日论坛发贴之星
日期:2016-07-18 06:20:00黑曼巴
日期:2016-12-26 16:00:3215-16赛季CBA联赛之江苏
日期:2017-06-26 11:05:5615-16赛季CBA联赛之上海
日期:2017-07-21 18:12:5015-16赛季CBA联赛之青岛
日期:2017-09-04 17:32:0515-16赛季CBA联赛之吉林
日期:2018-03-26 10:02:16程序设计版块每日发帖之星
日期:2016-07-15 06:20:0015-16赛季CBA联赛之江苏
日期:2016-07-07 18:37:512015亚冠之萨济拖拉机
日期:2015-08-17 12:21:08
9 [报告]
发表于 2015-06-24 21:17 |只看该作者
钻研精神,赞一个!

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

论坛徽章:
0
10 [报告]
发表于 2015-06-25 08:45 |只看该作者
回复 9# nswcfd
对滴

   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP