There are examples to operate on /proc file system.
/* procfs.c */
int init_module(){
int rv = 0;
Our_Proc_File = create_proc_entry("test", 0644, NULL);
printk(KERN_INFO "Trying to create /proc/test:/n");
if (Our_Proc_File == NULL){
rv= -ENOMEM;
remove_proc_entry("test", &proc_root);
printk(KERN_INFO "Error: Could not initialize /proc/test/n");
}
else{
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(KERN_INFO "Success!/n");
}
return rv;
}
void cleanup_module(){
remove_proc_entry("test", &proc_root);
printk(KERN_INFO "/proc/test removed/n");
}
/* procfs_io.c */
#include <linux/module.h> /*Specifically,a module*/
#include <linux/kernel.h> /*We're doing kernel work*/
#include <linux/proc_fs.h> /*Necessary because we use the proc fs*/
#define MESSAGE_LENGTH 80
static char Message[MESSAGE_LENGTH];
static struct proc_dir_entry *Our_Proc_File;
#define PROC_ENTRY_FILENAME "rw_test"
static ssize_t module_output(struct file *filp, /*see include/linux/fs.h */
char *buffer, /*buffer to fill with data*/
size_t length, /*length of the buffer */
loff_t *offset)
{
static int finished=0;
int i;
char message[MESSAGE_LENGTH + 30];
/*
* We return 0 to indicate end of file, that we have
* no more information. Otherwise, processes will
* continue to read from us in an endless loop.
*/
if(finished){
finished = 0;
return 0;
}
/*
* We use put_user to copy the string from the kernel's
* memory segment to the memory segment of the process
* that called us. get_user, BTW, is
* used for the reverse.
*/
sprintf(message, "Lastinput:%s", Message);
for(i=0; i<length && message[i]; i++)
put_user(message[i], buffer + i);
/*
* Notice, we assume here that the size of the message
* is below len, or it will be received cut. Inareal
* life situation, if the size of the message is less
* than len then we'd return len and on the second call
* start filling the buffer with the len+1'th byte of
* the message.
*/
finished = 1;
return i; /*Return the number of bytes "read"*/
}
static ssize_t module_input(struct file *filp, const char *buff,size_t len,loff_t *off)
{
int i;
/*
* Put the input into Message, where module_output
* will later be able to use it
*/
for(i = 0; i<MESSAGE_LENGTH - 1 && i < len; i++)
get_user(Message[i], buffer + i);
Message[i]='/0'; /*we want a standard, zero terminated string*/
return i;
}
/*
* This function decides whether to allow an operation
* (return zero) or not allow it (return a non-zero
* which indicates why it is not allowed).
*
* The operation can be one of the following values:
* 0 - Execute(run the"file" - meaningless in our case)
* 2 - Write(input to the kernel module)
* 4 - Read(output from the kernel module)
*
* This is the real function that checks file
* permissions. The permissions returned by ls -l are
* for referece only,and can be overridden here.
*/
static int module_permission(struct inode *inode, int op, struct nameidata *foo){
/*
* We allow everybody to read from our module, but
* only root (uid 0) may write to it
*/
if (op == 4 || (op == 2 && current->euid == 0))
return 0;
return -EACCES;
}
int module_open(struct inode *inode, struct file *file){
try_module_get(THIS_MODULE);
return 0;
}
int module_close(struct inode *inode, struct file *file){
module_put(THIS_MODULE);
return 0;
}
static struct file_operations File_Ops_4_Our_Proc_File = {
.read = module_output,
.write = module_input,
.open = module_open,
.release = module_close,
};
/*
* Inode operations for our proc file. We need it so
* we'll have some place to specify the file operations
* structure we want to use, and the function we use for
* permissions. It's also possible to specify functions
* to be called for anything else which could be done to
* an inode (although we don't bother, we just put
* NULL).
*/
static struct inode_operations Inode_Oops_4_Our_Proc_File = {
.permission = module_permission, /* check for permission */
};
int init_module(){
int rv = 0;
Our_Proc_File = create_proc_entry(PROC_ENTRY_FILENAME, 0644, NULL);
printk(KERN_INFO "Trying to create /proc/test:/n");
if (Our_Proc_File == NULL){
rv= -ENOMEM;
remove_proc_entry("test", &proc_root);
}
else{
Our_Proc_File->owner = THIS_MODULE;
Our_Proc_File->proc_iops = &Inode_Oops_4_Our_Proc_File;
Our_Proc_File->proc_fops = &File_Oops_4_Our_Proc_File;
Our_Proc_File->mode = S_IFREG | S_IRUGO | S_IWUSR;
Our_Proc_File->uid = 0;
Our_Proc_File->gid = 0;
Our_Proc_File->size = 80;
printk(KERN_INFO "Success!/n");
}
return rv;
}
void cleanup_module(){
remove_proc_entry(PROC_ENTRY_FILENAME, &proc_root);
}