何把内核中的信息打印到文件

时间:2008-01-16 13:09:57  来源:  作者:

我在内核中加了几个函数,要输出一些数据到文件中,以便处理,请问内核中提供了输出到文件的函数了么?谢谢!



 albcamus 回复于:2006-04-13 13:54:16


#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/syscalls.h>
#include <asm/unistd.h>
#include <asm/uaccess.h>

#define MY_FILE "/root/LogFile"

char buf[128];
struct file *file = NULL;



static int __init init(void)
{
mm_segment_t old_fs;
printk("Hello, I'm the module that intends to write messages to file.n");


if(file == NULL)
file = filp_open(MY_FILE, O_RDWR | O_APPEND | O_CREAT, 0644);
if (IS_ERR(file)) {
printk("error occured while opening file %s, exiting...n", MY_FILE);
return 0;
}

sprintf(buf,"%s", "The Messages.");

old_fs = get_fs();
set_fs(KERNEL_DS);
file->f_op->write(file, (char *)buf, sizeof(buf), &file->f_pos);
set_fs(old_fs);


return 0;
}

static void __exit fini(void)
{
if(file != NULL)
filp_close(file, NULL);
}

module_init(init);
module_exit(fini);
MODULE_LICENSE("GPL");




 xiaozhe2000 回复于:2006-04-13 14:21:14

谢谢斑竹!!!:P


 mq110 回复于:2006-04-13 14:36:17

我给你个打印在屏幕上的.


 mq110 回复于:2006-04-13 14:38:59

[CODE]
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/tty.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("mq110");
static void print_string(char *str)
{
    struct tty_struct *my_tty;
    my_tty = current->signal->tty;
    if (my_tty != NULL)
    {
        my_tty->driver->write(my_tty,0,str,strlen(str));
        my_tty->driver->write(my_tty,0,"1513",2);
    }
}
static int __init print_string_init(void)
{
    print_string("Hello world!");
    return 0;
}
static void __exit print_string_exit(void)
{
    print_string("Goodbye world!");
}
module_init(print_string_init);
module_exit(print_string_exit);
[/CODE]

我一般用putty登陆 编写kernel module. printk信息都存在/var/log/message里了.~

用这个程序就能显示在屏幕上了.你可以把print_string 符号导出来.


 思一克 回复于:2006-04-13 15:30:19

直接用PRINTK,然后在MESSAGES中选出来多好。

自己写的使用范围小(加入内核的函数会被其它函数调用,大部分情况不是mod_init直接调用的)。死机的情况多。printk则好多了。


 maluyao 回复于:2006-04-13 17:14:01

修改一下/etc/syslog.conf 文件
#kern.*       /dev/console

你打印的东西可能是某个级别的信息。比如说debug,这用printk 可以控制 。
那么就写程
kern.debug /var/log/kern_debug.log

-------------------------
printk(KERN_ALERT "Hello, worldn"); 
对应
/etc/syslog.conf 中的
kern.alert                      /kernel.txt

实验成功,修改后要执行
server syslogd restart 重启日志服务。
此方法等于用日志服务帮你做这个事情。该信息用
dmesg 命令也可以看到。

[ 本帖最后由 maluyao 于 2006-4-13 17:31 编辑 ]


 tomorrow0530 回复于:2006-04-20 14:17:32

引用:原帖由 思一克 于 2006-4-13 15:30 发表
直接用PRINTK,然后在MESSAGES中选出来多好。

自己写的使用范围小(加入内核的函数会被其它函数调用,大部分情况不是mod_init直接调用的)。死机的情况多。printk则好多了。 



死机!!哈哈,我的就是这样!:em10:
我把对文件的操作包了一层,以模块形式加载,把操作函数导出。
然后注册了个钩子函数,使用导出的函数,希望将包的信息写到指定文件。

情况时好时坏,有时一加载钩子函数就死机,有时多刷几次163之类的也死机。。。。

这个死机问题有没有解决的方法阿?谢谢


 albcamus 回复于:2006-04-20 14:24:37

引用:原帖由 tomorrow0530 于 2006-4-20 14:17 发表


死机!!哈哈,我的就是这样!:em10:
我把对文件的操作包了一层,以模块形式加载,把操作函数导出。
然后注册了个钩子函数,使用导出的函数,希望将包的信息写到指定文件。

情况时好时坏,有时一加载钩子 ... 



你hook的是什么函数?


 tomorrow0530 回复于:2006-04-20 14:42:46

自己写的,贴上来,个个提点意见了。。。。

#define __KERNEL__ 
#define MODULE
#include <linux/module.h>
#include <linux/kernel.h> //NIPQUAD()
#include <linux/netdevice.h> //struct net_device
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/in.h> //IPPROTO_TCP


static struct nf_hook_ops nfho;


static char *drop_if = "lo";


unsigned int hook_func(unsigned int hooknum,
                       struct sk_buff **skb,
                       const struct net_device *in,
                       const struct net_device *out,
                       int (*okfn)(struct sk_buff *))
{
  if (strcmp(in->name, drop_if) != 0) {

        static const char nulldevname[IFNAMSIZ]={0};
struct sk_buff *sb = *skb;

static unsigned int target_ip = 0;
static unsigned short target_port = 0;

static unsigned int source_ip = 0;
     static unsigned short source_port = 0;

static char *in_dev_name = "";
static char *out_dev_name = "";

struct file *filp;

struct iphdr *ip;
struct tcphdr *tcp;

        ip = sb->nh.iph;
        tcp = (struct tcphdr *)(sb->data + (sb->nh.iph->ihl * 4));

        in_dev_name = in?in->name:nulldevname;
        out_dev_name = out?out->name:nulldevname;
        source_ip = ip->saddr;
        target_ip = ip->daddr;
        target_port = ((((tcp->dest) >> 8 ) & 0xff )|(((tcp->dest) & 0xff) << 8)); 
        source_port = ((((tcp->source) >> 8 ) & 0xff )|(((tcp->source) & 0xff) << 8));


if ((filp = klib_fopen("/root/logfile", O_APPEND|O_WRONLY, S_IRUSR | S_IWUSR)) == NULL) {
        printk("Can't open filen");
        return NF_ACCEPT;
        }


if(ip->protocol == IPPROTO_TCP)
{
  klib_fprintf(filp,"Accepted TCP packet in_dev_name:%s out_dev_name:%s MAC:", in_dev_name, out_dev_name);
   if ((sb)->dev && (sb)->dev->hard_header_len && (sb)->mac.raw != (void*)ip) {
             int i;
             unsigned char *p = (sb)->mac.raw;
             for (i = 0; i < (sb)->dev->hard_header_len; i++,p++)
                 klib_fprintf(filp,"%02x%c", *p,
                        i==(sb)->dev->hard_header_len - 1
                        ? ' ':':');
           } else
               klib_fputc(' ', filp);

           klib_fprintf(filp,"  source_ip:%u.%u.%u.%u target_ip:%u.%u.%u.%u source_port:%u  target_port:%un", 
     NIPQUAD(source_ip), NIPQUAD(target_ip), source_port, target_port);
     klib_fprintf(filp,"  TCPn");
        }else 
    klib_fprintf(filp," NOT TCPn");
  
    

        klib_fclose(filp);
  }
        return NF_ACCEPT;   
}


static int init_func()
{

    nfho.hook     = hook_func;   
    nfho.hooknum  = NF_IP_PRE_ROUTING;
    nfho.pf       = PF_INET;
    nfho.priority = NF_IP_PRI_FIRST; 

    nf_register_hook(&nfho);
   
    return 0;
}
   

static void cleanup_func()
{
    nf_unregister_hook(&nfho);
}
module_init(init_func);
MODULE_LICENSE("GPL");
module_exit(cleanup_func);


 albcamus 回复于:2006-04-20 14:47:51

netfilter的hook点是在softirq的上下文中, 不可以睡眠(亦即:阻塞当前进程), 读写磁盘文件恰恰是可能导致睡眠的。 

记得wheelz斑竹的建议是: 如果你一定要在softirq上下文中读写文件, 那么, 生成一个内核线程来做这件事。


 tomorrow0530 回复于:2006-04-20 15:00:27

哦,原来是这样啊!
内核线程没有写过,先去补补这方面的东西!
有什么问题再过来请教各位了!
谢谢


 思一克 回复于:2006-04-20 15:15:34

换成printk


 tomorrow0530 回复于:2006-04-20 15:37:08

之前写了个用printk的,但因为和许多别的信息混在messages里,所以才想把它单独写到别的文件中!


 思一克 回复于:2006-04-20 15:40:19

PRINTK的每行前加一个标志MYLOG,

然后grep到一个文件中不就可以了吗


 tomorrow0530 回复于:2006-04-20 15:47:40

这也是个不错的办法!!
马上试试去!
谢谢了


 思一克 回复于:2006-04-20 16:11:00

printk也不是放什么地方都可以。它调用wake_up_XXXXXXXX了。实验着看。


 albcamus 回复于:2006-04-20 16:40:16

printk在哪里都可以用的:)


 思一克 回复于:2006-04-20 16:53:06

to alb,

放有些函数中不可以。比如和schedule()有关的函数,比如要switch context的许多地方,立即死机。
还有些地方(中断),理论上可以用,但实际随机地死机。


 albcamus 回复于:2006-04-21 09:51:24

引用:原帖由 思一克 于 2006-4-20 16:53 发表
to alb,

放有些函数中不可以。比如和schedule()有关的函数,比如要switch context的许多地方,立即死机。
还有些地方(中断),理论上可以用,但实际随机地死机。 



以前没遇到过呢, 有空试验下:)


 snow_insky 回复于:2006-04-21 11:36:22

不是吧,还这么老土,内核中已经提供了相应的函数,以便于在内核里操作文件,它们是:
filp_open,filp_close等,你自己找一下。不用自己写了。


 tomorrow0530 回复于:2006-04-21 13:42:47

试验结果,在hook函数上使用printk,没有问题。别的地方还没有试!!
用grep也很方便,谢谢思一克的点子!!


 tomorrow0530 回复于:2006-04-21 13:45:34

我说的那个就是把filp_open之类的包了一层,导出后。
用起来比较方便,不用包含头文件,就直接使用。


 思一克 回复于:2006-04-21 13:52:10

filp_open不行。楼主早都是这样做的。


 tomorrow0530 回复于:2006-04-21 14:41:01

在hook函数里用,filp_open之类的函数会造成死机!我的亲身体验,原因楼上的alb......已经说了!

[ 本帖最后由 tomorrow0530 于 2006-4-21 14:43 编辑 ]


 obrire 回复于:2006-04-24 23:51:34

没有不行的,我在内核多处使用,可以在用户间分类写很多文件
别是你VFS都没起来吧,那就麻烦了

你还可以采用procfs/relayfs/sysfs等记录嘛。
printk也行,因为一般是要初始化串口的/Bootloader和Kernel都要先做这事。
如果没有串口初始化呢?
采用其它文件格式记录也行的。

以上操作就是臭名昭著的克拉克Trojan一部分


 snow_insky 回复于:2006-04-25 09:33:50

我们的DSP镜像就是用filp_open之类的函数加载的,是不是自己不会用,就在这里说不行,唉,世道炎凉。

不仔细研究,就自己没搞出来就说不行。


 huyongzs 回复于:2006-04-25 15:07:58

诸位高手,你们发的这些代码怎么编译啊?
我用的是
gcc -g -o kprinter kernelprinter.c
不行啊,出现错误。


 albcamus 回复于:2006-04-25 15:42:35

>>如果没有串口初始化呢?
/dev/console初始化之前,可以用early_printk打印信息。

to huyongzs:
>>gcc -g -o kprinter kernelprinter.c
2.4和2.6编译过程不一样。 如果是前者, 去掉-g试试; 后者的话看精华区的文档吧(我转贴的ibm站点的那篇)


 zhangjiakouzf 回复于:2006-04-29 13:55:15

引用:原帖由 huyongzs 于 2006-4-25 15:07 发表
诸位高手,你们发的这些代码怎么编译啊?
我用的是
gcc -g -o kprinter kernelprinter.c
不行啊,出现错误。 



是不是应该加上-c选项呀
-c: 一个内核模块不是一个独立的可执行文件,而是一个内核在运行时用insmod动态连结的
目标文件。所以,内核应该在编译时使用 -c 选项。


 obrire 回复于:2006-04-30 00:53:00

引用:原帖由 albcamus 于 2006-4-25 15:42 发表
>>如果没有串口初始化呢?
/dev/console初始化之前,可以用early_printk打印信息。

to huyongzs:
>>gcc -g -o kprinter kernelprinter.c
2.4和2.6编译过程不一样。 如果是前者, 去掉-g试试;  ... 



在没有初始化串口时,在寄存器中,置入字符及输入,需要一些基本的转换
输入的全为字符,需将其转换为相对应的数据类型.
因此,在所有的Bootloader中,都几乎要做这一步.

不管在任何时候,需要操作串口接口,可以自己写一个操作函数.不管在任何时候
都可以输出.好像设置相关寄存器只有几句话.看三星和Moto的都这样.

-g 是包括调试信息之意.

如使用/dev/console,也就是/dev/tty(Sxx)等,都是在串口驱动启动以后;
之前,有一小段初始化串口代码,就是几句置数寄存器操作.而直接操作物理
接口,不受任何限制.以前我们都这样做的.包括下载Bootloader及调试.这时
没有任何输出,不可能用逻辑分析仪吧.不累死了.

但一般来讲,在内核空间是可以用文件操作的,因为VFS是Built-in内核的,大多数
情况是必须的.


 Cbook 回复于:2006-05-07 10:50:45

请教为什么上面的例子程序我都编译不过去啊
我用的是gcc  -g -c -O -Wall  XXX.c


 linux_ha 回复于:2007-09-24 17:24:57

用/proc就可以免去file_open的问题吧?:em21:


 hongmy525 回复于:2007-12-03 14:01:47

引用:原帖由 思一克 于 2006-4-20 15:40 发表 [url=http://linux.chinaunix.net/bbs/redirect.php?goto=findpost&pid=5048093&ptid=738197]
PRINTK的每行前加一个标志MYLOG,

然后grep到一个文件中不就可以了吗 



用处多多,谢谢:)




原文链接:http://linux.chinaunix.net/bbs/viewthread.php?tid=738197
转载请注明作者名及原文出处


文章评论

共有 位网友发表了评论 查看完整内容