驱动程序调试(一)————打印: prink, 自制proc文件

自己写proc文件是为了把打印信息和其他的信息区分开。。。。。

UBOOT传入console=ttySAC0 console=tty1
1. 内核处理UBOOT传入的参数
console_setup
add_preferred_console // 我想用名为”ttySAC0”的控制台,先记录下来

2. 硬件驱动的入口函数里:
    drivers/serial/s3c2410.c
        register_console(&s3c24xx_serial_console);      

3. printk
        vprintk
            /* Emit the output into the temporary buffer */
            // 先把输出信息放入临时BUFFER
            vscnprintf

            // Copy the output into log_buf.
            // 把临时BUFFER里的数据稍作处理,再写入log_buf
            // 比如printk("abc")会得到"<4>abc", 再写入log_buf
            // 可以用dmesg命令把log_buf里的数据打印出来重现内核的输出信息


            // 调用硬件的write函数输出
            release_console_sem();
                call_console_drivers(_con_start, _log_end);
                    // 从log_buf得到数据,算出打印级别
                    _call_console_drivers(start_print, cur_index, msg_level);           
                        // 如果可以级别够格打印
                        if ((msg_log_level < console_loglevel
                            __call_console_drivers
                                con->write(con, &LOG_BUF(start), end - start);

printk(KERN_DEBUG"%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);

mymsg.c

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>
#include <linux/proc_fs.h>

#define MYLOG_BUF_LEN 1024

struct proc_dir_entry *myentry;

static char mylog_buf[MYLOG_BUF_LEN];
static char tmp_buf[MYLOG_BUF_LEN];
static int mylog_r = 0;
static int mylog_r_for_read = 0;
static int mylog_w = 0;

static DECLARE_WAIT_QUEUE_HEAD(mymsg_waitq);

static int is_mylog_empty(void)
{
    return (mylog_r == mylog_w);
}

static int is_mylog_empty_for_read(void)
{
    return (mylog_r_for_read == mylog_w);
}

static int is_mylog_full(void)
{
    return ((mylog_w + 1)% MYLOG_BUF_LEN == mylog_r);
}

static void mylog_putc(char c)
{
    if (is_mylog_full())
    {
        /* 丢弃一个数据 */
        mylog_r = (mylog_r + 1) % MYLOG_BUF_LEN;

        if ((mylog_r_for_read + 1) % MYLOG_BUF_LEN == mylog_r)
        {
            mylog_r_for_read = mylog_r;
        }
    }

    mylog_buf[mylog_w] = c;
    mylog_w = (mylog_w + 1) % MYLOG_BUF_LEN;

    /* 唤醒等待数据的进程 */ 
    wake_up_interruptible(&mymsg_waitq);   /* 唤醒休眠的进程 */    
}

static int mylog_getc(char *p)
{
    if (is_mylog_empty())
    {
        return 0;
    }
    *p = mylog_buf[mylog_r];
    mylog_r = (mylog_r + 1) % MYLOG_BUF_LEN;
    return 1;
}

static int mylog_getc_for_read(char *p)
{
    if (is_mylog_empty_for_read())
    {
        return 0;
    }
    *p = mylog_buf[mylog_r_for_read];
    mylog_r_for_read = (mylog_r_for_read + 1) % MYLOG_BUF_LEN;
    return 1;
}


int myprintk(const char *fmt, ...)
{
    va_list args;
    int i;
    int j;

    va_start(args, fmt);
    i = vsnprintf(tmp_buf, INT_MAX, fmt, args);
    va_end(args);

    for (j = 0; j < i; j++)
        mylog_putc(tmp_buf[j]);

    return i;
}

static ssize_t mymsg_read(struct file *file, char __user *buf,
             size_t count, loff_t *ppos)
{
    int error = 0;
    int i = 0;
    char c;

    /* 把mylog_buf的数据copy_to_user, return */
    if ((file->f_flags & O_NONBLOCK) && is_mylog_empty_for_read())
        return -EAGAIN;

    //printk("%s %d\n", __FUNCTION__, __LINE__);
    //printk("count = %d\n", count);
    //printk("mylog_r = %d\n", mylog_r);
    //printk("mylog_w = %d\n", mylog_w);

    error = wait_event_interruptible(mymsg_waitq, !is_mylog_empty_for_read());

    //printk("%s %d\n", __FUNCTION__, __LINE__);
    //printk("count = %d\n", count);
    //printk("mylog_r = %d\n", mylog_r);
    //printk("mylog_w = %d\n", mylog_w);

    /* copy_to_user */
    while (!error && (mylog_getc_for_read(&c)) && i < count) {
        error = __put_user(c, buf);
        buf++;
        i++;
    }

    if (!error)
        error = i;

    return error;
}

static int mymsg_open(struct inode *inode, struct file *file)
{
    mylog_r_for_read = mylog_r;
    return 0;
}

const struct file_operations proc_mymsg_operations = {
    .open = mymsg_open,
    .read = mymsg_read,
};

static int mymsg_init(void)
{   
    myentry = create_proc_entry("mymsg", S_IRUSR, &proc_root);
    if (myentry)
        myentry->proc_fops = &proc_mymsg_operations;
    return 0;
}

static void mymsg_exit(void)
{
    remove_proc_entry("mymsg", &proc_root);
}

module_init(mymsg_init);
module_exit(mymsg_exit);

EXPORT_SYMBOL(myprintk);

MODULE_LICENSE("GPL");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值