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的,对应内核哪一部分代码?
求大神指点一下,告诉是哪部分代码,自己分析也行。感激不尽
求高人啊!! 求高人啊!! 本帖最后由 firocu 于 2015-06-24 10:24 编辑
个人观点:-)
我看了下代码, 子进程的标准输入输出初始化, 应该是clone的时候做得, 继承自父进程.
_do_fork-> copy_process->copy_files
之于什么时候终端变成/dev/pts, 这可能和系统初始化的进程有关, 比如systemd这些.
我记得好像用到getty这个工具了.
回复 1# 枫露清愁
回复 4# firocu
非常谢谢仁兄的回答,我去看下相关源码
看了一下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:39 编辑
我不知道你为什么这么执着于, 找到这个代码, 很多时候, 这都是大海捞针.
回复 6# 枫露清愁
对,pts是gnome-terminal生成的(CentOS6.4),谢谢仁兄。其实没啥原因,就是钻里面出不来了{:qq22:} 钻研精神,赞一个!
bash里不会有创建pts的代码,虚拟终端是从窗口程序继承过来的。 回复 9# nswcfd
对滴
页:
[1]