2、使用旧式proc接口的例子
本示例比较简单,先通过kmalloc函数分配一段TANGLINUX_LEN大小的内存,然后通过tanglinux_read和tanglinux_write函数来实现对这段内存的读写操作。
(1)、例子源代码
[cpp] view plain copy print ?
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/uaccess.h>
- #include <linux/proc_fs.h>
- #include <linux/slab.h>
- #include <linux/string.h>
-
- #define TANGLINUX_LEN 10
-
- static char *buf;
-
- static int proc_output(char *page)
- {
- char *p = page;
-
- p += sprintf(p, "%s", buf);
-
- return p - page;
- }
-
- static int tanglinux_read(char *page, char **start, off_t off,
- int count, int *eof, void *data)
- {
- int len;
-
- len = proc_output(page);
- if (len <= off + count)
- *eof = 1;
- *start = page + off;
- len -= off;
- if (len > count)
- len = count;
- if (len < 0)
- len = 0;
-
- return len;
- }
-
- static int tanglinux_write(struct file *file, const char __user *buffer,
- unsigned long count, void *data)
- {
- int ret;
-
- if (count > TANGLINUX_LEN) {
- printk("proc_test: buf is full!\n");
- return -ENOSPC;
- }
-
- ret = copy_from_user(buf, buffer, count);
- if (ret)
- return -EFAULT;
-
- return count;
- }
-
- static int __init tanglinux_init(void)
- {
- static struct proc_dir_entry *entry = NULL ;
-
- buf = kmalloc(TANGLINUX_LEN, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
- memset(buf, 0, TANGLINUX_LEN);
-
- entry = create_proc_entry("proc_test", S_IWUGO, NULL);
- if (!entry)
- {
- printk("proc_test: Couldn't create proc entry\n");
-
- return -EFAULT;
- }
- entry->read_proc = tanglinux_read;
- entry->write_proc = tanglinux_write;
-
- return 0;
- }
-
- static void __exit tanglinux_exit(void)
- {
- remove_proc_entry("proc_test", NULL);
- kfree(buf);
- }
-
- module_init(tanglinux_init);
- module_exit(tanglinux_exit);
-
- MODULE_AUTHOR("Richard Tang <[email protected]>");
- MODULE_LICENSE("GPL");
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/uaccess.h>
#include <linux/proc_fs.h>
#include <linux/slab.h>
#include <linux/string.h>
#define TANGLINUX_LEN 10
static char *buf;
static int proc_output(char *page)
{
char *p = page;
p += sprintf(p, "%s", buf);
return p - page;
}
static int tanglinux_read(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
int len;
len = proc_output(page);
if (len <= off + count)
*eof = 1;
*start = page + off;
len -= off;
if (len > count)
len = count;
if (len < 0)
len = 0;
return len;
}
static int tanglinux_write(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
int ret;
if (count > TANGLINUX_LEN) {
printk("proc_test: buf is full!\n");
return -ENOSPC;
}
ret = copy_from_user(buf, buffer, count);
if (ret)
return -EFAULT;
return count;
}
static int __init tanglinux_init(void)
{
static struct proc_dir_entry *entry = NULL ;
buf = kmalloc(TANGLINUX_LEN, GFP_KERNEL);
if (!buf)
return -ENOMEM;
memset(buf, 0, TANGLINUX_LEN);
entry = create_proc_entry("proc_test", S_IWUGO, NULL);
if (!entry)
{
printk("proc_test: Couldn't create proc entry\n");
return -EFAULT;
}
entry->read_proc = tanglinux_read;
entry->write_proc = tanglinux_write;
return 0;
}
static void __exit tanglinux_exit(void)
{
remove_proc_entry("proc_test", NULL);
kfree(buf);
}
module_init(tanglinux_init);
module_exit(tanglinux_exit);
MODULE_AUTHOR("Richard Tang <[email protected]>");
MODULE_LICENSE("GPL");
简要说明例子中主要函数的用法:
[cpp] view plain copy print ?
-
- extern struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
- struct proc_dir_entry *parent);
- extern void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
/* linux-2.6.38.8/include/linux/proc_fs.h */
extern struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
struct proc_dir_entry *parent);
extern void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
create_proc_entry函数用于在parent(当parent为NULL时即为在/proc目录下)目录下创建名为name的proc条目,参数mode用于设置此条目的访问权限以及文件类型(例子中设置proc_test的访问权限为所有用户可写,但只有拥有超级用户权限时才可以读)。
remove_proc_entry函数用于删除parent(当parent为NULL时即为在/proc目录下)目录下名为name的proc条目。
(2)、编译、加载和测试
[cpp] view plain copy print ?
-
- $ cat /proc/version
- Linux version 2.6.38-13-generic (buildd@roseapple) (gcc version 4.5.2 (Ubuntu/Linaro 4.5.2-8ubuntu4) ) #53-Ubuntu SMP Mon Nov 28 19:23:39 UTC 2011
-
-
- # Makefile
- KERN_DIR = /usr/src/linux-headers-2.6.38-13-generic/
-
- all:
- make -C $(KERN_DIR) M=`pwd` modules
-
- clean:
- make -C $(KERN_DIR) M=`pwd` modules clean
-
- obj-m += tanglinux.o
-
-
- $ make
- $ sudo insmod tanglinux.ko
-
-
- $ sudo cat /proc/proc_test
- $ echo "hello" > /proc/proc_test
- $ sudo cat /proc/proc_test
- hello
- $ echo "hello world" > /proc/proc_test
- bash: echo: write error: No space left on device
-
- $ dmesg | tail -1
- [ 427.791649] proc_test: buf is full!