自定义print函数缓存打印数据到环形缓冲区

发布者:智慧启迪最新更新时间:2016-04-01 来源: eefocus关键字:print函数  打印数据  环形缓冲区 手机看文章 扫描二维码
随时随地手机看文章
驱动程序:
 
#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);
 
       
        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");
 
===============================================================
解析:
当其他驱动程序调用自定义的myprintk函数打印数据时不会立即把数据打印在前台显示,而是把数据放在mylog_buf环形缓冲区中保存,当应用程序查看proc/mymsg时,即执行:cat /proc/mymsg时会调用mymsg_read函数读取环型缓冲区,如果缓冲区中有数据会调用__put_user返回,如果没有数据系统会休眠。
关键字:print函数  打印数据  环形缓冲区 引用地址:自定义print函数缓存打印数据到环形缓冲区

上一篇:应用调试-----使用strace命令来跟踪系统调用
下一篇:位置无关和位置相关

小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved