Proc文件系统是一种在用户态检查内核状态的机制。在proc下一般有如下子目录和文件:
Apm:高级电源管理信息
Bus:总线以及总线上的设备
Devices:可用的设备信息
Driver:已经启用的驱动程序
Interrupts:中断信息
Ioports:端口使用信息
Version:内核版本
上面的文件都具有如下特点:
1) 每个文件都有严格的权限(可读、可写、)
2) 可以用文本编辑器读取
3) 不仅可以有文件,也可以有子目录
4) 可以自己编写程序添加一个/proc目录下的文件
5) 文件的内容是动态创建的,并不存在于磁盘上
有关proc的文件在内核的描述符如下:
struct proc_dir_entry {
unsigned int low_ino;
unsigned short namelen;
const char *name;
mode_t mode;
nlink_t nlink;
uid_t uid;
gid_t gid;
loff_t size;
const struct inode_operations *proc_iops;
/*
* NULL ->proc_fops means "PDE is going away RSN" or
* "PDE is just created". In either case, e.g. ->read_proc won't be
* called because it's too late or too early, respectively.
*
* If you're allocating ->proc_fops dynamically, save a pointer
* somewhere.
*/
const struct file_operations *proc_fops;
struct proc_dir_entry *next, *parent, *subdir;
void *data;
read_proc_t *read_proc;
write_proc_t *write_proc;
atomic_t count; /* use count */
int pde_users; /* number of callers into module in progress */
spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */
struct completion *pde_unload_completion;
struct list_head pde_openers; /* who did ->open, but not ->release */
};
涉及到的函数:
int read_proc (char *buff, char ** stat, off_t off, int count, int *eof, void *data)
buff:把要返回给用户信息填写在buff里,最大不能超过PAGE_SIZE
stat:一般不使用
off:偏移量
count:用户要取的字节数
eof: 读取到文件尾,是需要将*eof设置为1
data:一般不用
int write_proc (struct file *file, const char *buffer, unsigned long count, void *data)
file:一般不使用
buffer:待写的数据所在的位置
count:待写数据大小
data: 一般不使用
创建proc文件:
struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
struct proc_dir_entry *parent)
name:要创建的文件名字
mode:要创建文件的属性,默认为07555
parent:这个文件的父目录
创建目录:
struct proc_dir_entry *proc_mkdir(const char *name,
struct proc_dir_entry *parent)
name:要创建的目录名
parent:这个目录的父目录
测试用例:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <linux/sched.h>
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Proc Module");
MODULE_ALIAS("proc module");
#define MAX_LENGTH 64
#define MAX_RECORD 5
#define F_NAME "pid"
#define D_NAME "tst"
#define P_NAME "/proc/" D_NAME "/" F_NAME
typedef struct {
pid_t pid;
char comm[TASK_COMM_LEN];
} pidcomm_t;
static int bufPos = 0;
pidcomm_t pidcommBuf[MAX_RECORD];
static struct proc_dir_entry *pid_entry;
static struct proc_dir_entry *dir_entry;
static int pid_write (struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
struct task_struct *_process;
char pid_buffer[MAX_LENGTH];
unsigned long pid_buffer_size = count;
if (pid_buffer_size > MAX_LENGTH)
pid_buffer_size = MAX_LENGTH;
memset(pid_buffer, 0, MAX_LENGTH);
if (copy_from_user (pid_buffer, buffer, pid_buffer_size))
return -EFAULT;
for_each_process (_process) {
char _tmp[MAX_LENGTH];
sprintf (_tmp, "%d\n", _process->pid);
if (!strcmp (_tmp, pid_buffer)) {
printk ("<1> The EXE file is: %20s \n", _process->comm);
pidcommBuf[bufPos].pid = _process->pid;
memset(pidcommBuf[bufPos].comm, 0, TASK_COMM_LEN);
strcpy(pidcommBuf[bufPos].comm, _process->comm);
bufPos = bufPos==MAX_RECORD-1 ? 0: bufPos+1;
}
}
return pid_buffer_size;
}
static int pid_read (char *page, char **start, off_t off,
int count, int *eof, void *data)
{
int i, ret, len = 0;
char *pos = page;
if (off > 0) {
*eof = 1;
return 0;
}
ret = sprintf(pos, "PID\tCOMMAND\n");
len += ret;
pos += ret;
for (i=0; i<MAX_RECORD; i++) {
if (0==pidcommBuf[i].pid)
break;
ret = sprintf(pos, "%d\t%s\n", pidcommBuf[i].pid,
pidcommBuf[i].comm);
len += ret;
pos += ret;
}
return len;
}
static int __init pid_init (void)
{
dir_entry = proc_mkdir(D_NAME, NULL);
if (!dir_entry) {
printk(KERN_ERR "Can't create /proc/" D_NAME "\n");
return -ENOMEM;
}
pid_entry = create_proc_entry (F_NAME, 0666, dir_entry);
if (!pid_entry) {
remove_proc_entry (F_NAME, dir_entry);
printk (KERN_ERR P_NAME " created failed\n");
return -ENOMEM;
}
pid_entry->read_proc = pid_read;
pid_entry->write_proc = pid_write;
printk ("<1> create " P_NAME " SUCCESSFULLY.\n");
return 0;
}
static void __exit pid_exit (void)
{
remove_proc_entry (F_NAME, dir_entry);
remove_proc_entry (D_NAME, NULL);
printk ("<1> Exit.\n");
}
module_init (pid_init);
module_exit (pid_exit);