本文内容源于tuxthink.blogspot.com 。主要介绍内核中proc entry的相关内容。

1. Background

As a user if we want to look into what the kernel is up to, we would need our application to read the data in kernel space. But applications running in the user space can not access the data in the kernel space, in such situations the proc file system comes to rescue.

The proc file system is an interface between the kernel and the userspace. Every entry in the proc file system provides some information from the kernel.

For eg:
The entry meminfo gives the details of the memory being used in the system.
To read the data in this entry just run
cat /proc/meminfo

Similarly the modules entry gives details of all the modules that are currently a part of the kernel.
cat /proc/modules

The proc file system is also very useful when we want to debug a kernel module. While debugging we might want to know the values of various variables in the module or may be the data that module is handling. In such situations we can create a proc entry for ourselves and dump what ever data we want to look into the entry.

The proc entry can also be used to pass data to the kernel by writing into the kernel, so there can be two kinds of proc entries

  1. An entry that only reads data from the kernel space
  2. An entry that reads as well as writes data into and from kernel space.

We will start by creating a proc entry for only reading first and then move to a a proc entry for write.

2. Creating a proc read entry

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
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include<linux/sched.h>

int read_proc(char *buf,char **start,off_t offset,int count,int *eof,void *data )
{
int len=0;
len += sprintf(buf+len, "Hello world");
return len;
}

void create_new_proc_entry()
{
create_proc_read_entry("hello",0,NULL,read_proc,NULL);
}

int proc_init (void) {
int ret;
create_new_proc_entry();
return 0;
}

void proc_cleanup(void) {
remove_proc_entry("hello",NULL);
}

MODULE_LICENSE("GPL");
module_init(proc_init);
module_exit(proc_cleanup);
1
2
insmod proc_read.ko
cat /proc/hello

For more details, just refer Creating a proc read entry.

3. Creating a Read/Write proc entry

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
#include <linux/module.h>
#include <linux/kernel.h>
#include <asm/uaccess.h>
#include <linux/cdev.h>
#include <linux/proc_fs.h>
#define MAX_PROC_SIZE 100

static char proc_data[MAX_PROC_SIZE];
static struct proc_dir_entry *proc_write_entry;

int read_proc(char *buf,char **start,off_t offset,int count,int *eof,void *data )
{
int len=0;
len = sprintf(buf,"\n %s\n ",proc_data);
return len;
}

int write_proc(struct file *file,const char *buf,int count,void *data )
{

if(count > MAX_PROC_SIZE)
count = MAX_PROC_SIZE;
if(copy_from_user(proc_data, buf, count))
return -EFAULT;
return count;
}

void create_new_proc_entry()
{
proc_write_entry = create_proc_entry("proc_entry",0666,NULL);
if(!proc_write_entry)
{
printk(KERN_INFO "Error creating proc entry");
return -ENOMEM;
}
proc_write_entry->read_proc = read_proc ;
proc_write_entry->write_proc = write_proc;
printk(KERN_INFO "proc initialized");
}

int proc_init (void) {
create_new_proc_entry();
return 0;
}

void proc_cleanup(void) {
printk(KERN_INFO " Inside cleanup_module\n");
remove_proc_entry("proc_entry",NULL);
}

MODULE_LICENSE("GPL");
module_init(proc_init);
module_exit(proc_cleanup);
1
2
3
4
$ insmod proc_write_read.ko
$ echo "Hello World" > /proc/proc_entry
$cat /proc/proc_entry
Hello world

For more details, just refer Creating a Read/Write proc entry.