diff options
| -rw-r--r-- | Makefile | 24 | ||||
| -rw-r--r-- | debug.c | 19 | ||||
| -rw-r--r-- | debug.h | 1 | ||||
| -rw-r--r-- | main.c | 44 | 
4 files changed, 81 insertions, 7 deletions
| @@ -1,14 +1,20 @@ -# causes weird file size, smaller than stripped? -ifeq ($(DEBUG),) -  ccflags-y += -g -endif -  # Makfile assignments:  #  := value at right is expanded and assigned at declaration time  #   = value at right is expanded only when it is used, hence it is a reference  #  ?= value at right is assigned only if the variable doesn't have a value  # -# + +# run following to compile with debug options +# $ DEBUG=1 make +ifneq ($(DEBUG),) +  DEBUG_FLAGS = -O0 -g -DHELLO_DEBUG +endif + +# see Documentation/kbuild/makefiles.txt +EXTRA_CFLAGS += $(DEBUG_FLAGS) + +ifneq ($(KERNELRELEASE),) +# call from kernel build system  # objects that are part of hello module (hello.o)  #hello-objs += main.o debug.o @@ -17,14 +23,20 @@ hello-y += main.o debug.o  # .ko module to be created  obj-m := hello.o +# normal makefile, not kbuild +else +  KERNELDIR ?= /lib/modules/$(shell uname -r)/build  # '-C' changes the dir  # '-M' causes the the kernel's toplevel Makefile to move back into this dir  #      before trying to build 'modules' target +#      and it informs kbuild that an external module is being built  all:  	make -C $(KERNELDIR) KCPPFLAGS="-I$(CURDIR)" M=$(PWD) modules +endif +  kclean:  	make -C $(KERNELDIR) M=$(PWD) clean @@ -105,3 +105,22 @@ int hello_debugfs_destroy(struct dentry *dir, struct dentry *file)      return 0;  } +/* + * Function implementing a read on /proc/hellomem, here we print few fields + * from internal data structure + */ +int hello_read_procmem(char *page, char **start, off_t off, int count, int *eof, void *data) +{ +    int len = 0; + +    struct hello_dev *dev = (struct hello_dev *) data; + +    len = sprintf(page, "hello module internal buffer is at: %p, with index of: %lu, " +            "buffer starts with: %c\n", dev->hello_buffer, dev->buff_index, +            dev->hello_buffer[0]); + +    *eof = 1; /* signify that we're done with dumping our internal structure */ + +    return len; +} + @@ -5,6 +5,7 @@ struct dentry;  int hello_debugfs_init(struct dentry **, struct dentry **);  int hello_debugfs_destroy(struct dentry *, struct dentry *); +int hello_read_procmem(char *, char **, off_t, int, int *, void *);  #endif @@ -1,4 +1,5 @@ -/* main.c +/* + * main.c   *   * r/w /dev/helloc0 character device   * @@ -16,6 +17,10 @@   * - ssize_t is an int, size_t is unsigned int, be careful   * - compile kernel with frame pointers to get better stack readout in case of an oops   * + * coding standars: + * - kernel official doc calls for tabs of width of 8, I'm using 4 spaced tab + * - ToDo: run Lindent + *   */  #include <linux/module.h> @@ -27,6 +32,7 @@  #include <linux/fs.h>  #include <linux/cdev.h>  #include <asm/uaccess.h> /* copy_*_user */ +#include <linux/proc_fs.h>  #include <main.h>  #include <debug.h> @@ -42,6 +48,34 @@ struct dentry *debugfs_file = NULL;  struct hello_dev *hello_device; +/* + * Use proc filesystem only when we are debugging, since it is discouraged in + * favor of sys filesystem + */ +#ifdef HELLO_DEBUG + +/* + * The proc filesystem is there to allow us to tap into driver's internal data + * structure within a kernel, in our case it will be struct hello_buffer + */ +static void hello_create_proc(void) +{ +    /* below function returns a proc_dir_entry that we will ignore, it's ok +     * proc_root in fs/proc/root.c:249 is a static variable that will have a +     * link to our raed entry +     */ +    create_proc_read_entry("hellomem", 0 /* default mode */, NULL /* parent dir */, +            hello_read_procmem /* function ptr to our read method */, +            hello_device /* our dev struct that kernel will pass for us that we will access */); +} + +static void hello_remove_proc(void) +{ +    remove_proc_entry("hellomem", NULL); +} + +#endif +  static int hello_create_debugfs(void)  {      int ret = 0; @@ -54,6 +88,8 @@ static int hello_create_debugfs(void)      return ret;  } + +  static ssize_t hello_read(struct file *filp, char __user *buff, size_t count, loff_t *f_pos)  {      struct hello_dev *dev = filp->private_data; @@ -185,6 +221,9 @@ static int __init hello_init(void)      }      hello_create_debugfs(); +#ifdef HELLO_DEBUG +    hello_create_proc(); +#endif      return 0; @@ -197,6 +236,9 @@ static void __exit hello_exit(void)  {      unregister_chrdev_region(MKDEV(hello_major, hello_minor), 1);      hello_debugfs_destroy(debugfs_dir, debugfs_file); +#ifdef HELLO_DEBUG +    hello_remove_proc(); +#endif      printk(KERN_INFO "[hello] module removed\n");  } | 
