diff --git a/LKMPG-3.16.html b/LKMPG-3.16.html index 7d18d8f..0172894 100644 --- a/LKMPG-3.16.html +++ b/LKMPG-3.16.html @@ -3,7 +3,7 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - + The Linux Kernel Module Programming Guide @@ -2151,201 +2151,84 @@ It's important to note that the standard roles of read and write are reversed in
-
/*
- *  procfs3.c -  create a "file" in /proc, use the file_operation way
- *              to manage the file.
- */
+
#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <linux/sched.h>
+#include <asm/uaccess.h>
 
-#include <linux/kernel.h>       /* We're doing kernel work */
-#include <linux/module.h>       /* Specifically, a module */
-#include <linux/proc_fs.h>      /* Necessary because we use proc fs */
-#include <linux/sched.h>        /* current_euid() */
-#include <asm/uaccess.h>        /* for copy_*_user */
-
-#define PROC_ENTRY_FILENAME     "buffer2k"
 #define PROCFS_MAX_SIZE         2048
+#define PROCFS_ENTRY_FILENAME   "buffer2k"
 
-/**
- * The buffer (2k) for this module
- *
- */
+struct proc_dir_entry *Our_Proc_File;
 static char procfs_buffer[PROCFS_MAX_SIZE];
-
-/**
- * The size of the data hold in the buffer
- *
- */
 static unsigned long procfs_buffer_size = 0;
 
-/**
- * The structure keeping information about the /proc file
- *
- */
-static struct proc_dir_entry *Our_Proc_File;
-
-/**
- * This funtion is called when the /proc file is read
- *
- */
-static ssize_t procfs_read(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 ssize_t procfs_read(struct file *filp, char *buffer,
+                           size_t length, loff_t *offset)
 {
     static int finished = 0;
-
-    /*
-     * 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 ) {
-        printk(KERN_INFO "procfs_read: END\n");
+    if(finished)
+    {
+        printk(KERN_DEBUG "procfs_read: END\n");
         finished = 0;
         return 0;
     }
-
     finished = 1;
-
-    /*
-     * We use put_to_user to copy the string from the kernel's
-     * memory segment to the memory segment of the process
-     * that called us. get_from_user, BTW, is
-     * used for the reverse.
-     */
-    if ( copy_to_user(buffer, procfs_buffer, procfs_buffer_size) ) {
+    if(copy_to_user(buffer, procfs_buffer, procfs_buffer_size))
         return -EFAULT;
-    }
-
-    printk(KERN_INFO "procfs_read: read %lu bytes\n", procfs_buffer_size);
-
-    return procfs_buffer_size;      /* Return the number of bytes "read" */
-}
-
-/*
- * This function is called when /proc is written
- */
-static ssize_t
-procfs_write(struct file *file, const char *buffer, size_t len, loff_t * off)
-{
-    if ( len > PROCFS_MAX_SIZE )    {
-        procfs_buffer_size = PROCFS_MAX_SIZE;
-    }
-    else {
-        procfs_buffer_size = len;
-    }
-
-    if ( copy_from_user(procfs_buffer, buffer, procfs_buffer_size) ) {
-        return -EFAULT;
-    }
-
-    printk(KERN_INFO "procfs_write: write %lu bytes\n", procfs_buffer_size);
-
+    printk(KERN_DEBUG "procfs_read: read %lu bytes\n", procfs_buffer_size);
     return procfs_buffer_size;
 }
-
-/*
- * 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)
+static ssize_t procfs_write(struct file *file,  const char *buffer,
+                            size_t len, loff_t *off)
 {
-    /*
-     * 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;
-
-    /*
-     * If it's anything else, access is denied
-     */
-    return -EACCES;
+    if(len>PROCFS_MAX_SIZE)
+        procfs_buffer_size = PROCFS_MAX_SIZE;
+    else
+        procfs_buffer_size = len;
+    if(copy_from_user(procfs_buffer, buffer, procfs_buffer_size))
+        return -EFAULT;
+    printk(KERN_DEBUG "procfs_write: write %lu bytes\n", procfs_buffer_size);
+    return procfs_buffer_size;
 }
-
-/*
- * The file is opened - we don't really care about
- * that, but it does mean we need to increment the
- * module's reference count.
- */
 int procfs_open(struct inode *inode, struct file *file)
 {
     try_module_get(THIS_MODULE);
     return 0;
 }
-
-/*
- * The file is closed - again, interesting only because
- * of the reference count.
- */
 int procfs_close(struct inode *inode, struct file *file)
 {
     module_put(THIS_MODULE);
-    return 0;               /* success */
+    return 0;
 }
 
 static struct file_operations File_Ops_4_Our_Proc_File = {
-    .read    = procfs_read,
-    .write   = procfs_write,
-    .open    = procfs_open,
-    .release = procfs_close,
+    .read       = procfs_read,
+    .write      = procfs_write,
+    .open       = procfs_open,
+    .release    = procfs_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_Ops_4_Our_Proc_File = {
-    .permission = module_permission,        /* check for permissions */
-};
-
-/*
- * Module initialization and cleanup
- */
 int init_module()
 {
-    /* create the /proc file */
-    Our_Proc_File = proc_create(PROC_ENTRY_FILENAME, 0644, NULL, NULL);
-
-    /* check if the /proc file was created successfuly */
-    if (Our_Proc_File == NULL){
-        printk(KERN_ALERT "Error: Could not initialize /proc/%s\n",
-               PROC_ENTRY_FILENAME);
+    Our_Proc_File = proc_create(PROCFS_ENTRY_FILENAME, 0644, NULL,&File_Ops_4_Our_Proc_File);
+    if(Our_Proc_File == NULL)
+    {
+        remove_proc_entry(PROCFS_ENTRY_FILENAME, NULL);
+        printk(KERN_DEBUG "Error: Could not initialize /proc/%s\n", PROCFS_ENTRY_FILENAME);
         return -ENOMEM;
     }
+    proc_set_size(Our_Proc_File, 80);
+    proc_set_user(Our_Proc_File,  GLOBAL_ROOT_UID, GLOBAL_ROOT_GID);
 
-    Our_Proc_File->proc_iops = &Inode_Ops_4_Our_Proc_File;
-    Our_Proc_File->proc_fops = &File_Ops_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 "/proc/%s created\n", PROC_ENTRY_FILENAME);
-
-    return 0;       /* success */
+    printk(KERN_DEBUG "/proc/%s created\n", PROCFS_ENTRY_FILENAME);
+    return 0;
 }
-
 void cleanup_module()
 {
-    remove_proc_entry(PROC_ENTRY_FILENAME, NULL);
-    printk(KERN_INFO "/proc/%s removed\n", PROC_ENTRY_FILENAME);
+    remove_proc_entry(PROCFS_ENTRY_FILENAME, NULL);
+    printk(KERN_DEBUG "/proc/%s removed\n", PROCFS_ENTRY_FILENAME);
 }
 
@@ -2402,10 +2285,6 @@ Seq_file provides basic functions for file_operations, as seq_read, seq_lseek, a

Example: procfs4.c

-

-TODO: this will be out of date because of create_proc_entry -

-
/**
@@ -2522,9 +2401,12 @@ MODULE_LICENSE("GPL");
 {
     struct proc_dir_entry *entry;
 
-    entry = create_proc_entry(PROC_NAME, 0, NULL);
-    if (entry) {
-        entry->proc_fops = &my_file_ops;
+    entry = proc_create(PROC_NAME, 0, NULL, &my_file_ops);
+    if(entry == NULL)
+    {
+        remove_proc_entry(PROC_NAME, NULL);
+        printk(KERN_DEBUG "Error: Could not initialize /proc/%s\n", PROC_NAME);
+        return -ENOMEM;
     }
 
     return 0;
@@ -2537,6 +2419,7 @@ MODULE_LICENSE("GPL");
 void cleanup_module(void)
 {
     remove_proc_entry(PROC_NAME, NULL);
+    printk(KERN_DEBUG "/proc/%s removed\n", PROC_NAME);
 }
 
diff --git a/LKMPG-3.16.org b/LKMPG-3.16.org index 91e8fec..a8f7729 100644 --- a/LKMPG-3.16.org +++ b/LKMPG-3.16.org @@ -1231,201 +1231,84 @@ It's important to note that the standard roles of read and write are reversed in *** Example: procfs3.c #+BEGIN_SRC c -/* - * procfs3.c - create a "file" in /proc, use the file_operation way - * to manage the file. - */ +#include +#include +#include +#include +#include -#include /* We're doing kernel work */ -#include /* Specifically, a module */ -#include /* Necessary because we use proc fs */ -#include /* current_euid() */ -#include /* for copy_*_user */ - -#define PROC_ENTRY_FILENAME "buffer2k" #define PROCFS_MAX_SIZE 2048 +#define PROCFS_ENTRY_FILENAME "buffer2k" -/** - * The buffer (2k) for this module - * - */ +struct proc_dir_entry *Our_Proc_File; static char procfs_buffer[PROCFS_MAX_SIZE]; - -/** - * The size of the data hold in the buffer - * - */ static unsigned long procfs_buffer_size = 0; -/** - * The structure keeping information about the /proc file - * - */ -static struct proc_dir_entry *Our_Proc_File; - -/** - * This funtion is called when the /proc file is read - * - */ -static ssize_t procfs_read(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 ssize_t procfs_read(struct file *filp, char *buffer, + size_t length, loff_t *offset) { static int finished = 0; - - /* - * 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 ) { - printk(KERN_INFO "procfs_read: END\n"); + if(finished) + { + printk(KERN_DEBUG "procfs_read: END\n"); finished = 0; return 0; } - finished = 1; - - /* - * We use put_to_user to copy the string from the kernel's - * memory segment to the memory segment of the process - * that called us. get_from_user, BTW, is - * used for the reverse. - */ - if ( copy_to_user(buffer, procfs_buffer, procfs_buffer_size) ) { + if(copy_to_user(buffer, procfs_buffer, procfs_buffer_size)) return -EFAULT; - } - - printk(KERN_INFO "procfs_read: read %lu bytes\n", procfs_buffer_size); - - return procfs_buffer_size; /* Return the number of bytes "read" */ -} - -/* - * This function is called when /proc is written - */ -static ssize_t -procfs_write(struct file *file, const char *buffer, size_t len, loff_t * off) -{ - if ( len > PROCFS_MAX_SIZE ) { - procfs_buffer_size = PROCFS_MAX_SIZE; - } - else { - procfs_buffer_size = len; - } - - if ( copy_from_user(procfs_buffer, buffer, procfs_buffer_size) ) { - return -EFAULT; - } - - printk(KERN_INFO "procfs_write: write %lu bytes\n", procfs_buffer_size); - + printk(KERN_DEBUG "procfs_read: read %lu bytes\n", procfs_buffer_size); return procfs_buffer_size; } - -/* - * 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) +static ssize_t procfs_write(struct file *file, const char *buffer, + size_t len, loff_t *off) { - /* - * 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; - - /* - * If it's anything else, access is denied - */ - return -EACCES; + if(len>PROCFS_MAX_SIZE) + procfs_buffer_size = PROCFS_MAX_SIZE; + else + procfs_buffer_size = len; + if(copy_from_user(procfs_buffer, buffer, procfs_buffer_size)) + return -EFAULT; + printk(KERN_DEBUG "procfs_write: write %lu bytes\n", procfs_buffer_size); + return procfs_buffer_size; } - -/* - * The file is opened - we don't really care about - * that, but it does mean we need to increment the - * module's reference count. - */ int procfs_open(struct inode *inode, struct file *file) { try_module_get(THIS_MODULE); return 0; } - -/* - * The file is closed - again, interesting only because - * of the reference count. - */ int procfs_close(struct inode *inode, struct file *file) { module_put(THIS_MODULE); - return 0; /* success */ + return 0; } static struct file_operations File_Ops_4_Our_Proc_File = { - .read = procfs_read, - .write = procfs_write, - .open = procfs_open, - .release = procfs_close, + .read = procfs_read, + .write = procfs_write, + .open = procfs_open, + .release = procfs_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_Ops_4_Our_Proc_File = { - .permission = module_permission, /* check for permissions */ -}; - -/* - * Module initialization and cleanup - */ int init_module() { - /* create the /proc file */ - Our_Proc_File = proc_create(PROC_ENTRY_FILENAME, 0644, NULL, NULL); - - /* check if the /proc file was created successfuly */ - if (Our_Proc_File == NULL){ - printk(KERN_ALERT "Error: Could not initialize /proc/%s\n", - PROC_ENTRY_FILENAME); + Our_Proc_File = proc_create(PROCFS_ENTRY_FILENAME, 0644, NULL,&File_Ops_4_Our_Proc_File); + if(Our_Proc_File == NULL) + { + remove_proc_entry(PROCFS_ENTRY_FILENAME, NULL); + printk(KERN_DEBUG "Error: Could not initialize /proc/%s\n", PROCFS_ENTRY_FILENAME); return -ENOMEM; } + proc_set_size(Our_Proc_File, 80); + proc_set_user(Our_Proc_File, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID); - Our_Proc_File->proc_iops = &Inode_Ops_4_Our_Proc_File; - Our_Proc_File->proc_fops = &File_Ops_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 "/proc/%s created\n", PROC_ENTRY_FILENAME); - - return 0; /* success */ + printk(KERN_DEBUG "/proc/%s created\n", PROCFS_ENTRY_FILENAME); + return 0; } - void cleanup_module() { - remove_proc_entry(PROC_ENTRY_FILENAME, NULL); - printk(KERN_INFO "/proc/%s removed\n", PROC_ENTRY_FILENAME); + remove_proc_entry(PROCFS_ENTRY_FILENAME, NULL); + printk(KERN_DEBUG "/proc/%s removed\n", PROCFS_ENTRY_FILENAME); } #+END_SRC @@ -1472,8 +1355,6 @@ digraph seq_file { Seq_file provides basic functions for file_operations, as seq_read, seq_lseek, and some others. But nothing to write in the /proc file. Of course, you can still use the same way as in the previous example. *** Example: procfs4.c -TODO: this will be out of date because of create_proc_entry - #+BEGIN_SRC c /** * procfs4.c - create a "file" in /proc @@ -1589,9 +1470,12 @@ int init_module(void) { struct proc_dir_entry *entry; - entry = create_proc_entry(PROC_NAME, 0, NULL); - if (entry) { - entry->proc_fops = &my_file_ops; + entry = proc_create(PROC_NAME, 0, NULL, &my_file_ops); + if(entry == NULL) + { + remove_proc_entry(PROC_NAME, NULL); + printk(KERN_DEBUG "Error: Could not initialize /proc/%s\n", PROC_NAME); + return -ENOMEM; } return 0; @@ -1604,6 +1488,7 @@ int init_module(void) void cleanup_module(void) { remove_proc_entry(PROC_NAME, NULL); + printk(KERN_DEBUG "/proc/%s removed\n", PROC_NAME); } #+END_SRC