github项目地址:https://github.com/superwujc
原文地址:
https://my.oschina.net/superwjc/blog/1816388
通过模块的方式调试内核时,printk()打印的信息默认只能通过dmesg的方式查看,可以通过以下方式,使用自定义的输出函数,将信息另打印至stdout。
模块程序:custom_printk.c
/* custom_printk.c */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/uaccess.h>
#include <linux/printk.h>
#define KPRINTF_MAX 1024
static long
custom_sys_write(unsigned int, const char __user *, size_t);
static int
custom_printk(const char *, ...);
static int __init start(void)
{
custom_printk("Hello there!\n");
return 0;
}
static void __exit end(void)
{
custom_printk("GoodBye!\n");
}
static long
custom_sys_write(unsigned int fd, const char __user *buf, size_t count)
{
long ret = -EBADF;
struct file *file = NULL;
mm_segment_t status;
loff_t offset;
if (!buf) {
printk("Write buffer was empty.\n");
return ret;
}
status = get_fs();
set_fs(KERNEL_DS);
file = fget(fd);
if (file) {
offset = file->f_pos;
ret = vfs_write(file, buf, count, &offset);
file->f_pos = offset;
fput(file);
}
set_fs(status);
return ret;
}
static int
custom_printk(const char *fmt, ...)
{
int ret = -EBADF;
char printf_buf[KPRINTF_MAX] = {0, };
va_list args;
va_list printk_args;
if (!fmt) {
printk("Format for custom_printk was empty.\n");
return ret;
}
memset(printf_buf, KPRINTF_MAX, 0);
va_start(args, fmt);
ret = vsnprintf(printf_buf, KPRINTF_MAX, fmt, args);
va_end(args);
if (ret > 0)
ret = (int)custom_sys_write(0, printf_buf, (unsigned int)ret);
else
printk("Something was wrong with format or snprintf.\n");
va_start(printk_args, fmt);
vprintk(fmt, printk_args);
va_end(printk_args);
return ret;
}
module_init(start);
module_exit(end);
MODULE_AUTHOR("test");
MODULE_LICENSE("GPL");
Makefile:
obj-m += custom_printk.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
EXTRA_CFLAGS = -g -O0 -Wno-declaration-after-statement
all:
make -C $(KDIR) M=$(PWD) modules
rm -rf *.ko.unsigned *.mod.c *.mod.o *.symvers *.o
.PHONY: clean
clean:
make -C $(KDIR) M=$(PWD) clean
编译并测试
make
make -C /lib/modules/3.10.0-862.2.3.el7.x86_64/build M=/code modules
make[1]: Entering directory `/usr/src/kernels/3.10.0-862.2.3.el7.x86_64'
CC [M] /code/custom_printk.o
Building modules, stage 2.
MODPOST 1 modules
CC /code/custom_printk.mod.o
LD [M] /code/custom_printk.ko
make[1]: Leaving directory `/usr/src/kernels/3.10.0-862.2.3.el7.x86_64'
rm -rf *.ko.unsigned *.mod.c *.mod.o *.symvers *.o
#
# insmod ./custom_printk.ko
Hello there!
#
# lsmod | grep custom_printk
custom_printk 12819 0
#
# modinfo ./custom_printk.ko
filename: /code/./custom_printk.ko
author: test
license: GPL
vermagic: 3.10.0-862.2.3.el7.x86_64 SMP mod_unload modversions
depends:
srcversion: D237B7F34015B61E554D9F7
rhelversion: 7.5
retpoline: Y
#
# rmmod custom_printk
GoodBye!
参考
http://bbs.chinaunix.net/thread-1928306-1-1.html
完~