时,都会从头打印。那么我们就需要将入口做一个拷贝,一个保存起来,一个进行变换。这样的话,当下一次读的时候,我们可以将保存的入口重新做个拷贝,然后让拷贝进行变化。具体程序如下:
#include
#include
#include
#include
#include
#include
#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");