<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    驅動程序調試方法之printk――自制proc文件(二)

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

    上一節的程序很振奮人心,我們自己實現了一個myprintk打印函數。但是這個函數存在一個致命的缺陷,那就是只能使用一次cat /proc/mymsg命令來讀取mylog_buf的值。這是因為讀到最后會出現:mylog_r == mylog_w,表示緩沖區為空,下一次就不能在讀到數據了。在本節里面我們就著手來解決這個問題,我們要實現的就是每次使用 cat /proc/mymsg 時,都會從頭打印。那么我們就需要將入口做一個拷貝,一個保存起來,一個進行變換。這樣的話,當下一次讀的時候,我們可以將保存的入口重新做個拷貝,然后讓拷貝進行變化。具體程序如下:

      #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;//這個用來拷貝mylog_r ,它將改變,但是mylog_r 不變 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); }   //這個函數是被myprintk函數調用的 static void mylog_putc(char c) { if (is_mylog_full()) { mylog_r = (mylog_r + 1) % MYLOG_BUF_LEN;                 /*加上下面三行的原因是:如果讀的時候,也一直在調用printk寫的話,                 *當寫的速度比較快的時候,可能會導致mylog_w超過mylog_r_for_read,                 *這時就需要更新mylog_r_for_read,使mylog_r_for_read 指向新的入口                 *當mylog_w超過入口mylog_r時,mylog_r會一直跟著更新的!                        */ 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_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;   if ((file->f_flags & O_NONBLOCK) && is_mylog_empty_for_read()) return -EAGAIN;   error = wait_event_interruptible(mymsg_waitq, !is_mylog_empty_for_read());   /* 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");   總結,關于這個函數,當我們在用戶空間,使用命令:cat /proc/mymsg時,首先會調用open函數,在open函數里面會將入口做一個拷貝,然后拿出一份來作為變化量,另外一個作為入口不改變。這樣,每次cat /proc/mymsg時,都會從入口處開始打印! RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全