Driver Debugging Method printk--homemade proc file (i)

Source: Internet
Author: User

First we need to figure out the proc mechanism, look at fs/proc/proc_misc.c this file, starting from the entry function:

proc_misc_init (void)#ifdef CONFIG_PRINTK {struct proc_dir_entry *entry;entry = create_proc_entry ("Kmsg", S_irusr, &proc_root);//Create a proc entry here Kmsgif (entry)entry->proc_fops = &proc_kmsg_operations;//Set operation function, see note 1 } Note 1:const struct File_operations proc_kmsg_operations = {. Read = Kmsg_read,. Poll = Kmsg_poll,. Open = Kmsg_open,. Release = Kmsg_release,};This operation function is used for multiple kmsg to operate so we can imitate to design!#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> struct proc_dir_entry *myentry; const struct File_operations proc_mymsg_operations = {}; static int mymsg_init (void){myentry = create_proc_entry ("mymsg", S_irusr, &proc_root);if (myentry)myentry->proc_fops = &proc_mymsg_operations; return 0;} void Mymsg_eixt (void){remove_proc_entry ("mymsg", &proc_root);}  Module_init (mymsg_init);Module_exit (mymsg_eixt); This function just creates a portal under the proc directory! After we load:ls/proc/mymsg-lPrint out the following information:- R--------1 0 0 0 Feb 4 13:37/proc/mymsg if we want to see/proc/mymsg content words: # cat/proc/mymsg Print out cat:read error:invalid argumentthat's for granted, because we didn't read the function at all!  So what we're going to do next is to finish this reading function, and what we're going to do in this reading function is to copy the data in the MYLOG_BUF into the user space. One of the key points is that our mylog_buf should be a ring queue, about the concept of a ring queue we first say: Front points to the queue header, rear points to the tail of the queue, and size indicates the queue length. Read only from the first reading, writing words can only be written from the tail! Write to the tail, then go back to start writing! When Front==rear, you can tell that the queue is empty. When (rear+1)/size==front, you can tell that the queue is full. The procedure is as follows:#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 1024x768 struct proc_dir_entry *myentry; static char Mylog_buf[mylog_buf_len];static char Tmp_buf[mylog_buf_len];static int mylog_r = 0; //used to identify readstatic int mylog_w = 0; //used to identify write static Declare_wait_queue_head (MYMSG_WAITQ); //Determine if the ring buffer is emptystatic int is_mylog_empty (void){return (Mylog_r = = mylog_w);}//Determine if the ring buffer is fullstatic int is_mylog_full (void){return ((mylog_w + 1)% Mylog_buf_len = = mylog_r);} /* Write buffer: If the buffer is full, let the cover fall off a read data* Otherwise, write directlyanother thing to do in the write buffer function is to wake up the waiting queue,this is because when the buffer is empty, if a read function is called, the processto enter the waiting queue, it is reasonable to wake the process when writing data*/static void Mylog_putc (char c){if (Is_mylog_full ()) {/ * Discard one data * /Mylog_r = (mylog_r + 1)% Mylog_buf_len; } mylog_buf[mylog_w] = c;mylog_w = (mylog_w + 1)% Mylog_buf_len; / * Wake up process waiting for data * /wake_up_interruptible (&MYMSG_WAITQ); / * Wake up the hibernate process * /} /* Read buffer: Returns 0 if the buffer is emptyOtherwise, a data is read from the header, returning 1*/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;} /* Print function: This function is to be written with reference to the sprintf function.* It converts the passed in parameter into a fixed format and puts it into a temporary buffer .* Then write the value of the ring buffer into the MYLOG_BUF buffer, see note 2*/int MYPRINTK (const char *fmt, ...){va_list args;int i;Int J; va_start (args, fmt);i = vsnprintf (Tmp_buf, Int_max, FMT, args);//Convert the passed in parameters into Tmp_bufva_end (args);For (j = 0; J < i; j + +)MYLOG_PUTC (Tmp_buf[j]);//Put tmp_buf inside the mylog_buf bufferreturn i;} /* Read function: This function is called when the command is called in the application space: Cat/proc/mymsg**/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; / * Copy_to_user The MYLOG_BUF data, return * / //If it is non-blocking and Mylog_buf is empty, then an error is returnedif ((File->f_flags & O_nonblock) && is_mylog_empty ())Return-eagain;         //If Mylog_buf is empty, the process enters the waiting queue, remember we are writing buffers//function inside will wake up the process this thing! error = wait_event_interruptible (MYMSG_WAITQ,!is_mylog_empty ()); / * Copy_to_user * ///First get a character from the buffer and copy it to the user space//If the buffer has information, it will get the character again, copy it to the user//Space until the buffer is emptyWhile (!error && (mylog_getc (&c)) && I < count) {error = __put_user (c, buf);//Copy the contents of C to user spacebuf++;i++; }if (!error)error = i;return error;} const struct File_operations proc_mymsg_operations = {. 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); / * Because MYPRINTK is the print statement we wrote ourselves.* So you need to export to be used, you need to declare when using:extern int myprintk (const char *fmt,...);*/Export_symbol (MYPRINTK); module_license ("GPL"); we are here to summarize: In this document we have done two things, one thing is to define a write function, when we use the command in user space: Cat/proc/mymsg, will call to this read function, this read function will Mylog_ The data in the BUF is copied to the user space, so where does the data in the mylog_buf come from? This is the other thing we do, we define a print function that writes the data that will be printed to a temporary buffer, and then pulls the data out of the temporary buffer into the mylog_buf. Cat/proc/mymsg will be the MYLOG_BUF in the data copied to the user space, it can be displayed!   NOTE 2:int sprintf (char * buf, const char *fmt, ...){va_list args;int i; va_start (args, fmt);i=vsnprintf (buf, Int_max, FMT, args);va_end (args);return i;}This is the sprintf function, which will pass in the parameters into the BUF buffer, we do is to put the value of this buffer in the MYLOG_BUF buffer inside! Quite ingenious Ah!  Next, let's test the function as follows: #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> Xtern int MYPRINTK (const char *fmt, ...); static int first_drv_init (void){MYPRINTK ("first_drv_init\n"); return 0;} static void First_drv_exit (void){MYPRINTK ("abcdefhg\n");} Module_init (first_drv_init);Module_exit (first_drv_exit);  module_license ("GPL"); load Proc.ko Firstwhen loading Test.kocat/proc/mymsg, print the following information:First_drv_initThis is exactly what we printed, and it worked!

Driver Debugging Method printk--homemade proc file (i)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.