glibc
printf ("hello World\n");
...
write(1,"hello World\n",sizeof("hello World\n"));
svc ...
linux
SYSCALL_DEFINE3(write
ksys_write
vfs_write
file->f_op->write_iter/即redirected_tty_write
tty_write
n_tty_write
tty->ops->write/对于串口即uart_write
__uart_start.isra.1
pl011_start_tx
l2c210_sync
redirected_tty_write 与 文件系统
drivers/tty/tty_io.c
static const struct file_operations console_fops = {
.write_iter = redirected_tty_write,
tty_init
cdev_init(&console_cdev, &console_fops);
cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1);
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console");
consdev = device_create_with_groups(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL, cons_dev_groups, "console");
问题
为什么printf底层的 redirected_tty_write 属于 cdev ,该cdev 和 /dev/console 有关系
那么 printf 用的 fd 1 和 /dev/console 有什么关系
我追到过 打开 /dev/console 的 过程, 明白 特殊文件系统 中 在open时替换了 file_operations
但是 printf 为什么 也能够调用到 redirected_tty_write?
fd 0 1 2 在进程创建的时候 就存在了 ,
我们明白,打开文件才会创建 fd,并会创建 struct file , 并填充 file->f_op->write_iter
所以可以说 是进程创建的时候 做了 这个 填充
进程创建的时候 只是做了 copy_files ,所以还是要看 init 进程的 file 配置
init 的file 配置 可以在启动时找到
在 kernel_init_freeable 中 调用了 console_on_rootfs
在 console_on_rootfs 中 ,打开了 /dev/console , 并 dup 出了 0 1 2
所以 0 1 2 对应的文件 都是 /dev/console
所以 printf 够调用到 /dev/console 对应的 redirected_tty_write 就 顺理成章了