新聞中心

        EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 自定義print函數(shù)緩存打印數(shù)據(jù)到環(huán)形緩沖區(qū)

        自定義print函數(shù)緩存打印數(shù)據(jù)到環(huán)形緩沖區(qū)

        作者: 時(shí)間:2016-11-21 來源:網(wǎng)絡(luò) 收藏
        驅(qū)動(dòng)程序:
        #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())
        {
        // 丟棄一個(gè)數(shù)據(jù) //
        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;
        // 喚醒等待數(shù)據(jù)的進(jìn)程 //
        wake_up_interruptible(&mymsg_waitq); // 喚醒休眠的進(jìn)程 //
        }
        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的數(shù)據(jù)copy_to_user, return //
        if ((file->f_flags & O_NONBLOCK) && is_mylog_empty_for_read())
        return -EAGAIN;
        //printk("%s %dn", __FUNCTION__, __LINE__);
        //printk("count = %dn", count);
        //printk("mylog_r = %dn", mylog_r);
        //printk("mylog_w = %dn", mylog_w);
        error = wait_event_interruptible(mymsg_waitq, !is_mylog_empty_for_read());
        //printk("%s %dn", __FUNCTION__, __LINE__);
        //printk("count = %dn", count);
        //printk("mylog_r = %dn", mylog_r);
        //printk("mylog_w = %dn", 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");
        ===============================================================
        解析:
        當(dāng)其他驅(qū)動(dòng)程序調(diào)用自定義的myprintk函數(shù)打印數(shù)據(jù)時(shí)不會立即把數(shù)據(jù)打印在前臺顯示,而是把數(shù)據(jù)放在mylog_buf環(huán)形緩沖區(qū)中保存,當(dāng)應(yīng)用程序查看proc/mymsg時(shí),即執(zhí)行:cat /proc/mymsg時(shí)會調(diào)用mymsg_read函數(shù)讀取環(huán)型緩沖區(qū),如果緩沖區(qū)中有數(shù)據(jù)會調(diào)用__put_user返回,如果沒有數(shù)據(jù)系統(tǒng)會休眠。


        評論


        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 彭泽县| 三河市| 韶关市| 金堂县| 舒城县| 墨竹工卡县| 凯里市| 云林县| 通辽市| 黄大仙区| 突泉县| 都安| 吉木萨尔县| 汤原县| 长海县| 镇巴县| 阆中市| 宝山区| 手机| 宕昌县| 册亨县| 武平县| 深水埗区| 阳春市| 沛县| 眉山市| 积石山| 鄄城县| 恩施市| 美姑县| 金山区| 阆中市| 安图县| 嘉鱼县| 图木舒克市| 临邑县| 中方县| 楚雄市| 鄂托克旗| 彰武县| 藁城市|