嵌入式串口打印信息重定向到当前终端界面
参考
在tty_init中会创建/dev/console:
int __init tty_init(void)
{
register_sysctl_init("dev/tty", tty_table);
cdev_init(&tty_cdev, &tty_fops);
cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1);
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty");
device_create(&tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty");
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");
#ifdef CONFIG_VT
vty_init(&console_fops);
#endif
return 0;
}
其中console_fops的定义如下:
static const struct file_operations console_fops = {
.llseek = no_llseek,
.read_iter = tty_read,
.write_iter = redirected_tty_write,
.splice_read = copy_splice_read,
.splice_write = iter_file_splice_write,
.poll = tty_poll,
.unlocked_ioctl = tty_ioctl,
.compat_ioctl = tty_compat_ioctl,
.open = tty_open,
.release = tty_release,
.fasync = tty_fasync,
};
写/dev/console的时候:
ssize_t redirected_tty_write(struct kiocb *iocb, struct iov_iter *iter)
{
struct file *p = NULL;
// 这里会有一个通过redirect实现重定向的操作
spin_lock(&redirect_lock);
if (redirect)
p = get_file(redirect);
spin_unlock(&redirect_lock);
/*
* We know the redirected tty is just another tty, we can
* call file_tty_write() directly with that file pointer.
*/
if (p) {
ssize_t res;
res = file_tty_write(p, iocb, iter);
fput(p);
return res;
}
return tty_write(iocb, iter);
}
trace日志如下:
6) | ksys_write() { /* <-__arm64_sys_write+0x24/0x34 */
6) 1.719 us | __fdget_pos(); /* <-ksys_write+0x3c/0xf0 ret=0xffffff88c230d200 */
6) | vfs_write() { /* <-ksys_write+0x80/0xf0 */
6) | security_file_permission() { /* <-vfs_write+0xb8/0x2d8 */
6) | selinux_file_permission() { /* <-security_file_permission+0x5c/0x84 */
6) + 52.865 us | file_has_perm(); /* <-selinux_file_permission+0x178/0x19c ret=0x0 */
6) + 55.990 us | } /* selinux_file_permission ret=0x0 */
6) + 58.177 us | } /* security_file_permission ret=0x0 */
6) 1.093 us | __get_task_ioprio(); /* <-vfs_write+0x188/0x2d8 ret=0x4004 */
6) | redirected_tty_write() { /* <-vfs_write+0x1ec/0x2d8 */
6) | file_tty_write() { /* <-redirected_tty_write+0x8c/0xc4 */
6) | tty_ldisc_ref_wait() { /* <-file_tty_write+0x64/0x2e8 */
6) 0.989 us | __ldsem_down_read_nested(); /* <-tty_ldisc_ref_wait+0x40/0x68 ret=0x1 */
6) 3.438 us | } /* tty_ldisc_ref_wait ret=0xffffff8854c76d80 */
6) | __check_object_size() { /* <-file_tty_write+0x11c/0x2e8 */
6) 0.937 us | check_stack_object(); /* <-__check_object_size+0x54/0x2a4 ret=0x0 */
6) 0.989 us | is_vmalloc_addr(); /* <-__check_object_size+0x84/0x2a4 ret=0x0 */
6) | pfn_is_map_memory() { /* <-__check_object_size+0xc4/0x2a4 */
6) 1.198 us | memblock_is_map_memory(); /* <-pfn_is_map_memory+0x24/0x40 ret=0x1 */
6) 3.073 us | } /* pfn_is_map_memory ret=0x1 */
6) 0.990 us | __check_heap_object(); /* <-__check_object_size+0x1a4/0x2a4 ret=0xffffff88c302b000 */
6) + 10.781 us | } /* __check_object_size ret=0xffffff88c302b000 */
6) | n_tty_write() { /* <-file_tty_write+0x160/0x2e8 */
6) | down_read() { /* <-n_tty_write+0xac/0x4d8 */
6) 1.302 us | preempt_count_add(); /* <-__down_read_trylock+0x4c/0x240 ret=0xffffffd19221585c */
6) 1.094 us | preempt_count_sub(); /* <-__down_read_trylock+0x1e4/0x240 ret=0xffffffd19221585c */
6) 5.417 us | } /* down_read ret=0x1 */
6) 2.657 us | add_wait_queue(); /* <-n_tty_write+0x130/0x4d8 ret=0xffffffd193381818 */
6) 1.146 us | tty_hung_up_p(); /* <-n_tty_write+0x164/0x4d8 ret=0x0 */
6) | tty_write_room() { /* <-n_tty_write+0x210/0x4d8 */
6) 2.760 us | uart_write_room(); /* <-tty_write_room+0x3c/0x54 ret=0xfff */
6) 4.688 us | } /* tty_write_room ret=0xfff */
6) | uart_write() { /* <-n_tty_write+0x314/0x4d8 */
6) 5.157 us | qcom_geni_serial_start_tx(); /* <-uart_write+0x250/0x30c ret=0xffffffd19490f490 */
6) + 10.781 us | } /* uart_write ret=0x1 */
6) | tty_write_room() { /* <-n_tty_write+0x354/0x4d8 */
6) 2.500 us | uart_write_room(); /* <-tty_write_room+0x3c/0x54 ret=0xffe */
6) 4.271 us | } /* tty_write_room ret=0xffe */
6) | do_output_char() { /* <-n_tty_write+0x364/0x4d8 */
6) | uart_write() { /* <-do_output_char+0x1b0/0x1e8 */
6) 4.166 us | qcom_geni_serial_start_tx(); /* <-uart_write+0x250/0x30c ret=0xffffffd19490f490 */
6) + 48.229 us | } /* uart_write ret=0x2 */
6) + 50.469 us | } /* do_output_char ret=0x2 */
6) | uart_flush_chars() { /* <-n_tty_write+0x3b8/0x4d8 */
6) | uart_start() { /* <-uart_flush_chars+0x18/0x28 */
6) 1.406 us | qcom_geni_serial_start_tx(); /* <-uart_start+0x13c/0x184 ret=0xffffffd19490f490 */
6) + 27.813 us | } /* uart_start ret=0xffffffd193381818 */
6) + 29.687 us | } /* uart_flush_chars ret=0xffffffd193381818 */
6) 2.708 us | remove_wait_queue(); /* <-n_tty_write+0x410/0x4d8 ret=0xffffffd193381818 */
6) | up_read() { /* <-n_tty_write+0x46c/0x4d8 */
6) 1.094 us | preempt_count_add(); /* <-__up_read+0x94/0x3d8 ret=0xffffffd19221585c */
6) 1.094 us | preempt_count_sub(); /* <-__up_read+0x170/0x3d8 ret=0xffffffd19221585c */
6) 5.104 us | } /* up_read ret=0xffffffd19221585c */
6) ! 129.427 us | } /* n_tty_write ret=0x2 */
6) | __wake_up() { /* <-file_tty_write+0x2bc/0x2e8 */
6) 0.260 us | __wake_up_common(); /* <-__wake_up+0x84/0xd8 ret=0x1 */
6) 2.865 us | } /* __wake_up ret=0x0 */
6) 0.937 us | ldsem_up_read(); /* <-file_tty_write+0x2c8/0x2e8 ret=0x1 */
6) ! 154.740 us | } /* file_tty_write ret=0x2 */
6) ! 158.125 us | } /* redirected_tty_write ret=0x2 */
6) 1.042 us | __fsnotify_parent(); /* <-vfs_write+0x228/0x2d8 ret=0x0 */
6) ! 223.802 us | } /* vfs_write ret=0x2 */
6) ! 230.729 us | } /* ksys_write ret=0x2 */
本文来自博客园,作者:摩斯电码,未经同意,禁止转载