tty0 显示的过程

来源:互联网 发布:mac os beta版 编辑:程序博客网 时间:2024/06/06 02:09
我们知道在调用prink输出的时候最终都会调用到call_console_drivers
static void call_console_drivers(int level,
                 const char *ext_text, size_t ext_len,
                 const char *text, size_t len)
{
    struct console *con;

    trace_console_rcuidle(text, len);

    if (!console_drivers)
        return;

    for_each_console(con) {
        if (exclusive_console && con != exclusive_console)
            continue;
        if (!(con->flags & CON_ENABLED))
            continue;
        if (!con->write)
            continue;
        if (!cpu_online(smp_processor_id()) &&
            !(con->flags & CON_ANYTIME))
            continue;
        if (con->flags & CON_EXTENDED)
            con->write(con, ext_text, ext_len);
        else
            con->write(con, text, len);
    }
}
而call_console_drivers 又会调用个个注册driver的write函数。
con_init 函数中下面的这段code中的visual_init会调用tty0往下模块的    vc->vc_sw->con_init(vc, init);函数

    for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) {
        vc_cons[currcons].d = vc = kzalloc(sizeof(struct vc_data), GFP_NOWAIT);
        INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK);
        tty_port_init(&vc->port);
        visual_init(vc, currcons, 1);
        vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT);
        vc_init(vc, vc->vc_rows, vc->vc_cols,
            currcons || !vc->vc_sw->con_save_screen);
    }
从visual_init 中我们知道vc->vc_sw = conswitchp;所以也就是调用conswitchp的con_init
而在setup_arch 中
#ifdef CONFIG_VT
#if defined(CONFIG_VGA_CONSOLE)
    conswitchp = &vga_con;
#elif defined(CONFIG_DUMMY_CONSOLE)
    conswitchp = &dummy_con;
#endif
#endif
我们的系统定义了CONFIG_VT和CONFIG_DUMMY_CONSOLE,因此conswitchp = &dummy_con;
而在drivers/video/console/dummycon.c 中
const struct consw dummy_con = {
    .owner =        THIS_MODULE,
    .con_startup =    dummycon_startup,
    .con_init =        dummycon_init,
    .con_deinit =    DUMMY,
    .con_clear =    DUMMY,
    .con_putc =        DUMMY,
    .con_putcs =    DUMMY,
    .con_cursor =    DUMMY,
    .con_scroll =    DUMMY,
    .con_switch =    DUMMY,
    .con_blank =    DUMMY,
    .con_font_set =    DUMMY,
    .con_font_get =    DUMMY,
    .con_font_default =    DUMMY,
    .con_font_copy =    DUMMY,
};
可以看到con_init和 con_putcs 都是空函数。而显示的话,那这部分是怎么真正的driver对接的呢?这里以fb为例,出列fb还有drm。
不管哪个硬件实现fb,都会调用register_framebuffer。
int
register_framebuffer(struct fb_info *fb_info)
{
    int ret;

    mutex_lock(&registration_lock);
    ret = do_register_framebuffer(fb_info);
    mutex_unlock(&registration_lock);

    return ret;
}

继续调用do_register_framebuffer,其中最重要的code如下:
fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event);
static int fbcon_event_notify(struct notifier_block *self,
                  unsigned long action, void *data)
{
    struct fb_event *event = data;
    struct fb_info *info = event->info;
    struct fb_videomode *mode;
    struct fb_con2fbmap *con2fb;
    struct fb_blit_caps *caps;
    int idx, ret = 0;

    /*
     * ignore all events except driver registration and deregistration
     * if fbcon is not active
     */
    if (fbcon_has_exited && !(action == FB_EVENT_FB_REGISTERED ||
                  action == FB_EVENT_FB_UNREGISTERED))
        goto done;

    switch(action) {
    case FB_EVENT_SUSPEND:
        fbcon_suspended(info);
        break;

    case FB_EVENT_FB_REGISTERED:
        ret = fbcon_fb_registered(info);
}
可见对应的FB_EVENT_FB_REGISTERED的处理函数为fbcon_fb_registered
/* called with console_lock held */
static int fbcon_fb_registered(struct fb_info *info)
{
    int ret = 0, i, idx;

    idx = info->node;
    fbcon_select_primary(info);

    if (info_idx == -1) {
        for (i = first_fb_vc; i <= last_fb_vc; i++) {
            if (con2fb_map_boot[i] == idx) {
                info_idx = idx;
                break;
            }
        }

        if (info_idx != -1)
            ret = do_fbcon_takeover(1);
    } else {
        for (i = first_fb_vc; i <= last_fb_vc; i++) {
            if (con2fb_map_boot[i] == idx)
                set_con2fb_map(i, idx, 0);
        }
    }

    return ret;
}
在fbcon_fb_registered 中会调用do_fbcon_takeover 来显示
static int do_fbcon_takeover(int show_logo)
{
    int err, i;

    if (!num_registered_fb)
        return -ENODEV;

    if (!show_logo)
        logo_shown = FBCON_LOGO_DONTSHOW;

    for (i = first_fb_vc; i <= last_fb_vc; i++)
        con2fb_map[i] = info_idx;

    err = do_take_over_console(&fb_con, first_fb_vc, last_fb_vc,
                fbcon_is_default);

    if (err) {
        for (i = first_fb_vc; i <= last_fb_vc; i++)
            con2fb_map[i] = -1;
        info_idx = -1;
    } else {
        fbcon_has_console_bind = 1;
    }

    return err;
}
do_fbcon_takeover 有又调用do_take_over_console 来接过console的显示
这样当在call_console_drivers 中调用tty0的write函数vt_console_print会调用
vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, vc->vc_x);
这样当调用do_take_over_console 之后,这里的con_putcs就对应是具体driver的con_putcs函数了



0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 三星手机显示解析包出现问题怎么办 三星手机下载解析包出现问题怎么办 两万的流动大棚给整坏了怎么办 劲舞团抽奖领了一样的衣服怎么办 win系统ps界面字体太小怎么办 任何网页都变成监控登录界面怎么办 微信启动录音的尝试被拒绝怎么办 微信传到电脑的文件打不开怎么办 转转网账号出租时遇到防沉迷怎么办 如果买了王者号结果有防沉迷怎么办 苹果手机一直显示验证失败怎么办呢 安装包证书异常导致安装失败怎么办 qq飞车忘了几区的怎么办 5e在游戏里卡住不动怎么办 别人发的cdr文件打开太慢怎么办 qq红包充值话费未到账怎么办 qq飞车充值至尊皇冠不到账怎么办 微信支付金额超过单日限制怎么办 不小心在qq钱包中充错话费怎么办 衣服质量不好穿了几次就坏了怎么办 手机丢了找到手机店的人怎么办 在手机店买手机买贵了怎么办 王者荣耀好多没对的东西怎么办 用电脑玩游戏键盘不管用怎么办? 王者荣耀跨系统送皮肤领不到怎么办 电脑使用迅雷时提示缓存过高怎么办 扣扣安全中心动态密码忘记了怎么办 pu管两头固定了中间换截怎么办 自己架设的传奇不能注册帐号怎么办 天堂2第八章读取服务端错误怎么办 苹果手机王者荣耀下了不能玩怎么办 苹果手机摔了一下触屏失灵怎么办 华为机回复出厂设置帐号忘了怎么办 华为手机里突然有个pp助手怎么办 华为手机与电脑连接不上怎么办 买房交了首付贷不了款怎么办 手机买贵了实体店不肯退怎么办 在实体店里手机买贵了怎么办 红米手机开启不了安装系统怎么办? 捡个荣耀8双清后要账号怎么办 荣耀7x升级8.0后耗电快怎么办