文章目錄
-
- /proc檔案系統介紹
- /proc檔案系統特點
- 核心描述
-
- 建立proc檔案
- 建立目錄
- 删除目錄/檔案
- 讀寫
- 實作流程
- mini6410下的執行個體代碼
-
- 在/proc下先建立目錄後建立檔案
/proc檔案系統介紹
/proc檔案系統是一種特殊的、由軟體建立的檔案系統,核心使用它向外界導出資訊。/proc下面的每一個檔案都綁定于一個核心函數,使用者讀取其中的檔案時,該函數動态地生成檔案的“”内容“”
比如:通過/proc/meminfo,查詢目前記憶體的使用情況。
簡言之:proc檔案系統時一種在使用者态檢查核心狀态的機制。
/proc檔案下的常見子目錄
子目錄/檔案名 | 内容描述 |
---|---|
apm | 進階電源管理資訊 |
bus | 總線以及總線上的裝置 |
devices | 可用的裝置資訊 |
driver | 已經啟用的驅動程式 |
interrupts | 中斷資訊 |
ioports | 端口使用資訊 |
version | 核心版本 |
/proc檔案系統特點
-
每個檔案都規定了嚴格的權限
(可讀?可寫?哪個使用者可讀?哪個使用者可寫?)
- 可以用文本編輯程式讀取(more指令,cat指令,vi程式等)
- 不僅可以有檔案,還可以有子目錄
- 可以自己編寫程式添加一個/proc目錄下的問價
- 檔案的内容都是動态建立的,并不存在與磁盤上。
核心描述
proc核心描述:
struct proc_dir_entry
{
.......
read_proc_t *read_proc;
write_proc_t *write_proc;
.......
}
建立proc檔案
struct proc_dir_entry create_proc_entry(const char *name,mode_t mode,struct proc_dir_entry parent)
**功能:**建立proc檔案
參數:
- name:要建立的檔案名
- mode:要建立的檔案的屬性 預設0755
- parent:這個檔案的父目錄
建立目錄
*struct proc_dir_entry * proc_mkdir(const char *name,struct proc_dir_entry parent)
功能:建立proc目錄
參數:
- name:要建立的目錄名
- parent:這個目錄的父目錄
删除目錄/檔案
void remove_proc_entry(const char *name,struct proc_dir_entry *parent)
功能:删除proc目錄或檔案
參數:
- name:要删除的檔案或目錄名
- parent:所在的父目錄
讀寫
為了能讓使用者讀寫添加的proc問價,需要挂接上讀寫回調函數:
read_proc
write_proc
(1)讀操作
*int read_func(char *buffer,char **stat,off_t off,int count,int *peof,void data)
參數:
- buffer:把要傳回給使用者的資訊寫在buffer裡,最大不超過PAGE_SIZE
- stat:一般不使用
- off:偏移量
- count:使用者要讀取的位元組數
- peof:讀到檔案尾時,需要把*peof置1
- data:一般不使用
(2)寫操作
*int write_func(struct file *file,const char *buffer,unsigned long count,void data)
參數:
- file:該proc檔案對應的file結構,一般忽略
- buffer:待寫的資料所在位置
- count:待寫資料的大小
- data:一般不使用
實作流程
實作一個proc檔案的流程:
- 調用create_proc_entry建立一個struct proc_dir_entry。
- 對建立的struct proc_dir_entry進行指派:read_proc,mode,owner,size,write_proc等。
mini6410下的執行個體代碼
(1)proc.c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#define procfs_name "proctest"
struct proc_dir_entry *Our_Proc_File;
int procfile_read(char *buffer,
char **buffer_location,
off_t offset,int buffer_length,int *eof,void *data)
{
int ret;
ret = sprintf(buffer,"HelloWorld\n");
return ret;
}
int proc_init()
{
Our_Proc_File = create_proc_entry(procfs_name,0644,NULL);
if(Our_Proc_File == NULL)
{
remove_proc_entry(procfs_name,NULL);
printk(KERN_ALERT "Error:Counld not initialize /proc/%s\n",procfs_name);
return -ENOMEM;
}
Our_Proc_File->read_proc = procfile_read;
Our_Proc_File->owner = THIS_MODULE;
Our_Proc_File->mode = S_IFREG | S_IRUGO;
Our_Proc_File->uid = 0;
Our_Proc_File->gid = 0;
Our_Proc_File->size = 37;
printk("/proc/%s created\n",procfs_name);
return 0;
}
void proc_exit()
{
remove_proc_entry(procfs_name,NULL);
printk(KERN_INFO "/proc/%s removed\n",procfs_name);
}
module_init(proc_init);
module_exit(proc_exit);
(2) Makefile
ifneq ($(KERNELRELEASE),)
obj-m := proc.o
else
KDIR := /home/zhangbin/mini6410/linux-2.6.38
all:
make -C $(KDIR) M=$(PWD) ARCH=arm CROSS_COMPILE=arm-linux-
clean:
rm -f *.ko *.o *.mod.c *.symvers
endif
(3)在mini6410闆子上的運作效果
在/proc下先建立目錄後建立檔案
(1)proc1.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
static char msg[255];
struct proc_dir_entry *pfile;
static char *mydir;
static int myproc_read(char *page,char **start,off_t off,int count,int *eof,void *data){
int len = strlen(msg);
if(off >= len)
return 0;
if(count > len - off)
count = len - off;
memcpy(page+off,msg+off,count);
return off + count;
}
static int myproc_write(struct file *file,const char __user *buffer,unsigned long count,void *data)
{
unsigned long count2 = count;
if(count2 >= sizeof(msg))
count2 = sizeof(msg) - 1;
if(copy_from_user(msg,buffer,count2))
return -EFAULT;
msg[count2] = '\0';
return count;
}
static int __init myproc_init(void)
{
mydir = proc_mkdir("mydir",NULL);
if(!mydir)
{
printk(KERN_ERR "can't create /proc/mydir\n");
return -1;
}
pfile = create_proc_entry("pool",0666,mydir);
if(!pfile)
{
printk(KERN_ERR "can't create /proc/mydir/pool\n");
remove_proc_entry("mydir",NULL);
return -1;
}
pfile->read_proc = myproc_read;
pfile->write_proc = myproc_write;
return 0;
}
static void __exit myproc_exit()
{
remove_proc_entry("pool",mydir);
remove_proc_entry("mydir",NULL);
}
module_init(myproc_init);
module_exit(myproc_exit);
(2)Makefile
ifneq ($(KERNELRELEASE),)
obj-m := proc1.o
else
KDIR := /home/zhangbin/mini6410/linux-2.6.38
all:
make -C $(KDIR) M=$(PWD) ARCH=arm CROSS_COMPILE=arm-linux-
clean:
rm -f *.ko *.o *.mod.c *.symvers
endif
(3)在mini6410開發闆上驗證如下: