核心游记之 printk

接下去看printk

还是宏 CONFIG_PRINTK 在s3c2410中定义了改宏

 

#ifdef CONFIG_PRINTK
asmlinkage int vprintk(const char *fmt, va_list args)
    __attribute__ ((format (printf, 1, 0)));
asmlinkage int printk(const char * fmt, ...)
    __attribute__ ((format (printf, 1, 2)));


#else


static inline int vprintk(const char *s, va_list args)
    __attribute__ ((format (printf, 1, 0)));
static inline int vprintk(const char *s, va_list args) { return 0; }//直接返回
static inline int printk(const char *s, ...)
    __attribute__ ((format (printf, 1, 2)));
static inline int printk(const char *s, ...) { return 0; }   //直接返回
#endif

继续往下看

asmlinkage int printk(const char *fmt, ...)
{
    va_list args;
    int r;

    va_start(args, fmt);
    r = vprintk(fmt, args);
    va_end(args);

    return r;
}

vprintk如下:终于来了个大家伙!该函数负责解析并组成打印格式,

asmlinkage int vprintk(const char *fmt, va_list args)
{
    unsigned long flags;
    int printed_len;
    char *p;
    static char printk_buf[1024];
    static int log_level_unknown = 1;

    preempt_disable();                            //空操作
    if (unlikely(oops_in_progress) && printk_cpu == smp_processor_id())
        /* If a crash is occurring during printk() on this CPU,
         * make sure we can't deadlock */
        zap_locks(); // 初始化锁logbuf_lock和互斥量console_sem

    /* This stops the holder of console_sem just where we want him */
    spin_lock_irqsave(&logbuf_lock, flags); //加锁
    printk_cpu = smp_processor_id();

    /* Emit the output into the temporary buffer */
    printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args);

// 将打印信息拷贝到printk_buf缓冲中,printk("%d, %s", 5, "hello")  printk_buf中将是5,hello格式化后的数据不带'/0'

    /*
     * Copy the output into log_buf.  If the caller didn't provide
     * appropriate log level tags, we insert them here
     */
    for (p = printk_buf; *p; p++) {
        if (log_level_unknown) { //打印级别未知,则添家打印级别
                        /* log_level_unknown signals the start of a new line */
            if (printk_time) {    //由于没有定义CONFIG_PRINTK_TIME宏 printk_time = 0;
                int loglev_char;
                char tbuf[50], *tp;
                unsigned tlen;
                unsigned long long t;
                unsigned long nanosec_rem;

                /*
                 * force the log level token to be
                 * before the time output.
                 */
                if (p[0] == '<' && p[1] >='0' &&
                   p[1] <= '7' && p[2] == '>') {
                    loglev_char = p[1];
                    p += 3;
                    printed_len += 3;
                } else {
                    loglev_char = default_message_loglevel
                        + '0';
                }
                t = printk_clock();
                nanosec_rem = do_div(t, 1000000000);
                tlen = sprintf(tbuf,
                        "<%c>[%5lu.%06lu] ",
                        loglev_char,
                        (unsigned long)t,
                        nanosec_rem/1000);

                for (tp = tbuf; tp < tbuf + tlen; tp++)
                    emit_log_char(*tp);
                printed_len += tlen - 3;
            } else {                                                 //由于printk_time = 0,直接跳转到这里
                if (p[0] != '<' || p[1] < '0' ||
                   p[1] > '7' || p[2] != '>') { // 如果没有设置打印级别,那么默认0级
                    emit_log_char('<');
                    emit_log_char(default_message_loglevel
                        + '0');
                    emit_log_char('>');
                }
                printed_len += 3;
            }
            log_level_unknown = 0;
            if (!*p)
                break;
        }
        emit_log_char(*p); //打印信息已经保存到log_buf中
        if (*p == '/n') //如遇到 '/n' 则表示一条打印结束,那么打印级别需要从新设置
            log_level_unknown = 1;
    }

    if (!cpu_online(smp_processor_id())) {
        /*
         * Some console drivers may assume that per-cpu resources have
         * been allocated.  So don't allow them to be called by this
         * CPU until it is officially up.  We shouldn't be calling into
         * random console drivers on a CPU which doesn't exist yet..
         */
        printk_cpu = UINT_MAX;
        spin_unlock_irqrestore(&logbuf_lock, flags);
        goto out;
    }
    if (!down_trylock(&console_sem)) {
        console_locked = 1;
        /*
         * We own the drivers.  We can drop the spinlock and let
         * release_console_sem() print the text
         */
        printk_cpu = UINT_MAX;
        spin_unlock_irqrestore(&logbuf_lock, flags);
        console_may_schedule = 0;
        release_console_sem();
    } else {
        /*
         * Someone else owns the drivers.  We drop the spinlock, which
         * allows the semaphore holder to proceed and to call the
         * console drivers with the output which we just produced.
         */
        printk_cpu = UINT_MAX;
        spin_unlock_irqrestore(&logbuf_lock, flags); //释放锁,打印信息已经保存到log_buf中,等待打印
    }
out:
    preempt_enable();
    return printed_len;
}

 

printk和printf不同,他首先输出到系统的一个缓冲区内,大约4k,如果登记了console,则调用console->wirte函数输出,否则就一直在buffer里呆着。所以,用printk输出的信息,如果超出了4k,会冲掉前面的。在系统引导起来后,用dmesg看的也就是这个buffer中的东东。

此时的信息还在buf中躺着呢。。因为console还没有初始化。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值