/* procfs.c * * Create a "file" in proc * From the Linux Kernel Module Programming Guide, Ch 5.1 * modified to match proc_fs.h * 2009.07.24 * What should I do about BUF_LEN? Is that a system constant? (no). * Do I use it to set my own bufer len? Do I pick my own BUF_LEN? (yes, yes). * How does the system get my user_buffer_len? (It's a value parameter). * 2009.07.24 * This version works using both get_info and read_proc. The output * indicates that get_info was actually registered and called, but * I could not get the program to work without filling in the slot * for proc_read as well. * */ #include /* kernel work */ #include /* building a kernel module */ #include /* working with the proc fs */ #define BUF_LEN 80 /* Prototypes */ int my_get_info(char *sys_buffer, char **user_buffer, off_t file_pos, int my_buffer_length, int zero); int my_read(char *sys_buffer, char **user_buffer, off_t file_pos, int my_buffer_len, int *eof, void *data); int init_module(void); void cleanup_module(void); /* * My function to get info for the proc file read. * Matches the prototype for the get_info function field of the proc_dir_entry * struct in proc_fs.h */ int my_get_info(char *sys_buffer, char **user_buffer, off_t file_pos, int my_buffer_length, int zero) { /* bytes actually used */ int len = 0; /* I'll supply the buffer instead of using the kernel's (why?) */ static char my_buffer[BUF_LEN]; static int count = 1; /* count the number of reads to this proc file */ printk(KERN_ALERT "procfs module get_info: entering.\n"); /* Make sure we're only called once by the kernel read */ if (file_pos > 0) { printk(KERN_ALERT "procfs module get_info: leaving via shortcut.\n"); return 0; } len = sprintf(my_buffer, "count: %d\n", count); count++; /* pass on the buffer to the kernel */ *user_buffer = my_buffer; printk(KERN_ALERT "procfs module get_info: leaving.\n"); return len; } /* * My function to read a proc file. * Matches the prototype for the read_proc function field of the proc_dir_entry * struct in proc_fs.h */ int my_read(char *sys_buffer, char **user_buffer, off_t file_pos, int my_buffer_len, int *eof, void *data) { printk(KERN_ALERT "procfs module read_proc: entering.\n"); printk(KERN_ALERT "procfs module read_proc: leaving.\n"); return 0; } /* * The proc_dir_entry struct from proc_fs.h */ struct proc_dir_entry my_proc_file = { 0, /* unsigned short low_ino; inode number filled in by proc_register */ 4, /* unsigned short namelen; length of file name */ "test", /* const char *name; file name */ S_IFREG | S_IRUGO, /* mode_t mode; file mode, ugo read permission */ 1, /* nlink_t nlink; number of links */ 0, /* uid_t uid; uid */ 0, /* gid_t gid; gid */ 0, /* unsigned long size; size of file as reported by ls (most give 0) */ NULL, /* struct inode_operations * ops; no inode functions*/ my_get_info, /* int (*get_info)(char *, char **, off_t, int, int); */ NULL, /* void (*fill_inode)(struct inode *, int); nothing to fill in inode */ NULL, NULL, NULL, /* struct proc_dir_entry *next, *parent, *subdir; */ NULL, /* void *data; */ my_read, /* int (*read_proc)(char *page, char **start, off_t off, int count, int *eof, void *data); */ NULL, /* int (*write_proc)(struct file *file, const char *buffer, unsigned long count, void *data); */ NULL, /* int (*readlink_proc)(struct proc_dir_entry *de, char *page); */ 0, /* unsigned int count; */ /* use count */ 0, /* int deleted; */ /* delete flag */ }; /* Initialize the module - register the proc file in 2.2 kernel */ int init_module(void) { printk(KERN_ALERT "proc_fs module: load and register.\n"); return proc_register(&proc_root, &my_proc_file); } /* Clean up the module - unregister our file from /proc */ void cleanup_module(void) { printk(KERN_ALERT "proc_fs module: unregister and unload.\n"); proc_unregister(&proc_root, my_proc_file.low_ino); }