85 printk 输出丢失数据
前言
问题来自于 chinaunix 社区论坛
kernel 中读取文件, 只读取到文件部分内容(前1013个字节)
呵呵 看到这个的时候, 我也不太信, 呵呵 但是实际测试一下, 当真如此
然后使用了一个 简单的测试用例 测试了一下
这个问题主要是 printk 的输出的限制
测试用例
这里显示模拟的实际情况, 编写的一个测试用例
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h> /* for sleep */
#include <linux/wait.h> /* for wait queue */
#include <linux/time.h>
#include <linux/delay.h>
#include <linux/slab.h> /* for kmalloc() */
#include <linux/workqueue.h>static int __init shared_workqueue_init(void)
{int i=0;int len = 2048;char *my_data = (char *)kmalloc(len, GFP_KERNEL);for(i=0; i<len; i++) {*(my_data+i) = '6';}pr_info(" before printk ");printk(KERN_INFO "%s", my_data);kfree(my_data);return 0;
}module_init(shared_workqueue_init);static void __exit shared_workqueue_exit(void)
{printk(KERN_INFO "module exit\n ");
}module_exit(shared_workqueue_exit);MODULE_AUTHOR("e665106");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("A simple shared-workqueue Module");
MODULE_ALIAS("a simplest module");
这里尝试输出了一个 >= 2048 的一个字符串 my_data
但是实际 输出的结果如下, 然后可以统计一下 这里的 6 的数量为 989 个
(initramfs) insmod printkOverflow/printkOverflow.ko
[ 320.781890] module exit
[ 320.781890]
[ 336.013758] before printk
[ 336.019556] 66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666
prink 的输出处理
这里的 fmt 为传入的 “%s”, args 为传入的 my_data 的字符串
text 为输出的一个缓冲, sizeOf(text) 为 992, 计算的方式为 1024 – 32 = 992
textbuf 的空间最长长度定义如下, 会保留一部分缓冲用于输出 时间, 颜色信息
那么也应该是 992 才对, 为什么输出的 6 的数量是 989 呢?
前两个字符是表示颜色的字符
最后一个字符为 字符串的结束符 ‘\0’ 因此 最终有效的 ‘6’ 仅有 992 – 2 -1 为 989 个
vsnprintf 的测试
测试用例如下, 新建了一个字符串, 长度为 2047
然后使用 vsnprintf 来将其中的 1024 个内容复制到 buff, 然后观察 buff 的相关信息
这个 在不同的平台上面实现略微有所不同
#include "stdio.h"
#include "stdarg.h"int my_printf(char *buff, int bufLen, const char *fmt, ...);int main() {int i = 0;int srcLen = 2048;char *srcBuf = (char *) malloc(srcLen);for (i = 0; i < srcLen; i++) {*(srcBuf + i) = '6';}*(srcBuf + srcLen - 1) = 0;int bufLen = 1024;char *buff = (char *) malloc(bufLen);int copiedCount = my_printf(buff, bufLen, "%s", srcBuf);printf("%s\n", srcBuf);printf("%s\n", buff);printf("%d\n", copiedCount);return 0;}int my_printf(char *buff, int bufLen, const char *fmt, ...) {va_list ap;va_start(ap, fmt);int copiedCount = vsnprintf(buff, bufLen, "%s", ap);va_end(ap);return copiedCount;
}
在 windows 上面执行结果如下
srcBuf 中 2047 个 ‘6’, 是正确的
buff 中 1024 个 ‘6’, 并且后面还携带了遗传特殊字符, 这说明 vsnprintf 中未将 buff 的最后一个字节设置为 0
copiedCount 这里是响应的是拷贝出错, 但是数据 依然拷贝到 buff 中了
6666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666
6666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666����������������
-1
在 linux 上面执行结果如下
srcBuf 中 2047 个 ‘6’, 是正确的
buff 中 1023 个 ‘6’, buff 中最后一个字节为 0, 因此这里 输出的是 1023 个 ‘6’
copiedCount 这里是响应的是原字符串的长度, 2047
6666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666
666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666
2047
但是值得注意的是, 虽然 vsnprintf 名字相同, 参数的传递相同
但是 这里测试用例的 vsnprintf 和 内核的 vsnprintf 不是同一个
这里测试用例中断的 vsnprintf 实现如下, 是 glibc 的一个实现
然后实现方式 类似于 printf
完