/proc文件系統

/proc文件系統 

在Linux中有一個另外的機制來使內核及內核模塊發送信息給進程——/proc文件系統。 
/proc文件系統最初是設計使得輕易獲得進程的信息(從名字能夠看出),如今卻被任意一塊 
有內容須要報告的內核使用,好比擁有模塊列表的/proc/modules和擁有內存使用統計信息的 
/proc/meminfo。 
使用proc文件系統的方法很象使用設備驅動——你建立一個數據結構,使之包含/proc 
文件須要的所有信息,包括全部函數的句柄(在咱們的例子裏只有一個,在試圖讀取/proc 
文件時調用)。而後,用init_module註冊這個結構,用cleanup_module註銷。 
咱們使用proc_register_dynamic(注3.1)的緣由是咱們不但願決定之後在文件中使用的 
索引節點數,而是讓內核來決定它,爲了防止衝突。標準的文件系統是在磁盤上而不是在內 
存(/proc的位置在內存),在這種狀況下節點數是一個指向文件的索引節點所在磁盤地址的 
指針。這個索引節點包含了文件的有關信息好比文件的訪問權限以及指向磁盤地址的指真或 
者文件數據的位置。 
由於在文件打開或關閉時咱們沒有調用,因此在模塊裏無處可放宏 
MOD_INC_USE_COUNT和MOD_DEC_USE_COUNT,並且假如文件被打開了或者模塊被 
刪除了,就沒有辦法來避免這個結果。下一章咱們將會看到一個更困難的處理/proc的方法, 
可是也更加靈活,也可以解決這個問題。 
ex procfs.c 

/* procfs.c - create a "file" in /proc 
* Copyright (C) 1998-1999 by Ori Pomerantz 
*/ 


/* The necessary header files */ 

/* Standard in kernel modules */ 
#include /* We're doing kernel work */ 
#include /* Specifically, a module */ 

/* Deal with CONFIG_MODVERSIONS */ 
#if CONFIG_MODVERSIONS==1 
#define MODVERSIONS 
#include 
#endif 


/* Necessary because we use the proc fs */ 
#include 



/* In 2.2.3 /usr/include/linux/version.h includes a 
* macro for this, but 2.0.35 doesn't - so I add it 
* here if necessary. */ 
#ifndef KERNEL_VERSION 
#define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c)) 
#endif 



/* Put data into the proc fs file. 

Arguments 
========= 
1. The buffer where the data is to be inserted, if 
you decide to use it. 
2. A pointer to a pointer to characters. This is 
useful if you don't want to use the buffer 
allocated by the kernel. 
3. The current position in the file. 
4. The size of the buffer in the first argument. 
5. Zero (for future use?). 


Usage and Return Value 
====================== 
If you use your own buffer, like I do, put its 
location in the second argument and return the 
number of bytes used in the buffer. 

A return value of zero means you have no further 
information at this time (end of file). A negative 
return value is an error condition. 


For More Information 
==================== 
The way I discovered what to do with this function 
wasn't by reading documentation, but by reading the 
code which used it. I just looked to see what uses 
the get_info field of proc_dir_entry struct (I used a 
combination of find and grep, if you're interested), 
and I saw that it is used in /fs/proc/array.c. 

If something is unknown about the kernel, this is 
usually the way to go. In Linux we have the great 
advantage of having the kernel source code for 
free - use it. 
*/ 
int procfile_read(char *buffer, 
char **buffer_location, 
off_t offset, 
int buffer_length, 
int zero) 

int len; /* The number of bytes actually used */ 

/* This is static so it will still be in memory 
* when we leave this function */ 
static char my_buffer[80]; 

static int count = 1; 

/* We give all of our information in one go, so if the 
* user asks us if we have more information the 
* answer should always be no. 

* This is important because the standard read 
* function from the library would continue to issue 
* the read system call until the kernel replies 
* that it has no more information, or until its 
* buffer is filled. 
*/ 
if (offset > 0) 
return 0; 

/* Fill the buffer and get its length */ 
len = sprintf(my_buffer, 
"For the %d%s time, go away!\n", count, 
(count % 100 > 10 && count % 100 < 14) ? "th" : 
(count % 10 == 1) ? "st" : 
(count % 10 == 2) ? "nd" : 
(count % 10 == 3) ? "rd" : "th" ); 
count++; 

/* Tell the function which called us where the 
* buffer is */ 
*buffer_location = my_buffer; 

/* Return the length */ 
return len; 



struct proc_dir_entry Our_Proc_File = 

0, /* Inode number - ignore, it will be filled by 
* proc_register[_dynamic] */ 
4, /* Length of the file name */ 
"test", /* The file name */ 
S_IFREG | S_IRUGO, /* File mode - this is a regular 
* file which can be read by its 
* owner, its group, and everybody 
* else */ 
1, /* Number of links (directories where the 
* file is referenced) */ 
0, 0, /* The uid and gid for the file - we give it 
* to root */ 
80, /* The size of the file reported by ls. */ 
NULL, /* functions which can be done on the inode 
* (linking, removing, etc.) - we don't 
* support any. */ 
procfile_read, /* The read function for this file, 
* the function called when somebody 
* tries to read something from it. */ 
NULL /* We could have here a function to fill the 
* file's inode, to enable us to play with 
* permissions, ownership, etc. */ 
}; 





/* Initialize the module - register the proc file */ 
int init_module() 

/* Success if proc_register[_dynamic] is a success, 
* failure otherwise. */ 
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,0) 
/* In version 2.2, proc_register assign a dynamic 
* inode number automatically if it is zero in the 
* structure , so there's no more need for 
* proc_register_dynamic 
*/ 
return proc_register(&proc_root, &Our_Proc_File); 
#else 
return proc_register_dynamic(&proc_root, &Our_Proc_File); 
#endif 

/* proc_root is the root directory for the proc 
* fs (/proc). This is where we want our file to be 
* located. 
*/ 



/* Cleanup - unregister our file from /proc */ 
void cleanup_module() 

proc_unregister(&proc_root, Our_Proc_File.low_ino); 
}
相關文章
相關標籤/搜索