在做内核驱动开发的时候,可以使用/proc下的文件,获取相应的信息,以便调试。

大多数/proc下的文件是只读的,但为了示例的完整性,都提供了写方法。

方法一:使用 create_proc_entry 创建 proc 文件(简单,但写操作有缓冲区溢出的危险);

方法二:使用 proc_createseq_file 创建 proc 文件(较方法三简洁);

方法三:使用 proc_create_dataseq_file 创建 proc 文件(较麻烦,但比较完整);

示例四:在 proc 文件中使用内核链表的一个示例(用的方法三)。


方法三、

proc_test03.c 源码

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
 
// global var
static char *str = NULL;
 
// linux/seq_file.h
// void * (*start) (struct seq_file *m, loff_t *pos);
// void (*stop) (struct seq_file *m, void *v);
// void * (*next) (struct seq_file *m, void *v, loff_t *pos);
// int (*show) (struct seq_file *m, void *v);
 
/**
* author:  aran
* fuction: seq_operations -> start
*/
static void *my_seq_start(struct seq_file *m, loff_t *pos)
{
	if (0 == *pos)
	{
		++*pos;
		return (void *)1; // return anything but NULL, just for test
	}
	return NULL;
}
 
/**
* author:  aran
* fuction: seq_operations -> next
*/
static void *my_seq_next(struct seq_file *m, void *v, loff_t *pos)
{
	// only once, so no next
	return NULL;
}
 
/**
* author:  aran
* fuction: seq_operations -> stop
*/
static void my_seq_stop(struct seq_file *m, void *v)
{
	// clean sth.
	// nothing to do
}
 
/**
* author:  aran
* fuction: seq_operations -> show
*/
static int my_seq_show(struct seq_file *m, void *v)
{
	seq_printf(m, "current kernel time is %llu\n", (unsigned long long) get_jiffies_64());
	seq_printf(m, "str is %s\n", str);
 
	return 0; //!! must be 0, or will show nothing T.T
}
 
// global var
static struct seq_operations my_seq_fops = 
{
	.start	= my_seq_start,
	.next	= my_seq_next,
	.stop	= my_seq_stop,
	.show	= my_seq_show,
};
 
// file_operations
// int (*open) (struct inode *, struct file *)
// ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *)
 
/**
* author:  aran
* fuction: file_operations -> open
*/
static int proc_seq_open(struct inode *inode, struct file *file)
{
	return seq_open(file, &my_seq_fops);
}
 
/**
* author:  aran
* fuction: file_operations -> write
*/
static ssize_t proc_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *f_pos)
{
	//分配临时缓冲区
	char *tmp = kzalloc((count+1), GFP_KERNEL);
	if (!tmp)
		return -ENOMEM;
 
	//将用户态write的字符串拷贝到内核空间
	//copy_to|from_user(to,from,cnt)
	if (copy_from_user(tmp, buffer, count)) {
		kfree(tmp);
		return -EFAULT;
	}
 
	//将str的旧空间释放,然后将tmp赋值给str
	kfree(str);
	str = tmp;
 
	return count;
}
 
// global var
static struct file_operations proc_seq_fops = 
{
	.owner		= THIS_MODULE,
	.open		= proc_seq_open,
	.read		= seq_read,
	.write		= proc_seq_write,
	.llseek		= seq_lseek,
	.release	= seq_release,
};
 
static int __init my_init(void)
{
	struct proc_dir_entry *file;
 
	// create "/proc/proc_seq" file
	file = proc_create_data(
		"jif",		// name
		0666,		// mode
		NULL,		// parent dir_entry
		&proc_seq_fops,	// file_operations
		NULL		// data
		);
	if (NULL == file)
	{
		printk("Count not create /proc/jif file!\n");
		return -ENOMEM;
	}
 
	return 0;
}
 
static void __exit my_exit(void)
{
	remove_proc_entry("jif", NULL);
	kfree(str);
}
 
module_init(my_init);
module_exit(my_exit);
 
MODULE_AUTHOR("aran");
MODULE_LICENSE("GPL");

Makefile文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
obj-m	:= proc_test03.o
KERNEL	:= /lib/modules/`uname -r`/build #for mint/ubuntu
#KERNEL	:= /lib/modules/`uname -r`/source #for redhat
 
all:
	make -C $(KERNEL) M=`pwd` modules
 
install:
	make -C $(KERNEL) M=`pwd` modules_install
	depmod -A
 
clean:
	make -C $(KERNEL) M=`pwd` clean

测试结果

测试结果