Tying Everything Together

Example 2-1 is a revision of Example 1-2 that uses its own malloc_type structure instead of the kernel-defined M_TEMP.[2] Example 2-1 should clarify any misunderstandings you may have about MALLOC_DEFINE and MALLOC_DECLARE.

Note

To save space, the functions echo_open, echo_close, echo_write, and echo_read aren’t listed here, as they haven’t been changed.

Example 2-1. echo-2.0.c

#include <sys/param.h>
  #include <sys/module.h>
  #include <sys/kernel.h>
  #include <sys/systm.h>

  #include <sys/conf.h>
  #include <sys/uio.h>
  #include <sys/malloc.h>

  #define BUFFER_SIZE     256

 MALLOC_DECLARE(M_ECHO);
 MALLOC_DEFINE(M_ECHO, "echo_buffer", "buffer for echo driver");

  static d_open_t         echo_open;
  static d_close_t        echo_close;
  static d_read_t         echo_read;
  static d_write_t        echo_write;

  static struct cdevsw echo_cdevsw = {
          .d_version =    D_VERSION,
          .d_open =       echo_open,
          .d_close =      echo_close,
          .d_read =       echo_read,
          .d_write =      echo_write,
          .d_name =       "echo"
  };

  typedef struct echo {
          char buffer[BUFFER_SIZE];
          int length;
  } echo_t;

  static echo_t *echo_message;
  static struct cdev *echo_dev;

  static int
  echo_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
  {
  ...
  }

  static int
  echo_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
  {
  ...
  }

  static int
  echo_write(struct cdev *dev, struct uio *uio, int ioflag)
  {
  ...
  }

  static int
  echo_read(struct cdev *dev, struct uio *uio, int ioflag)
  {
  ...
  }

  static int
  echo_modevent(module_t mod __unused, int event, void *arg __unused)
  {
          int error = 0;

          switch (event) {
          case MOD_LOAD:
                  echo_message = malloc(sizeof(echo_t), M_ECHO, M_WAITOK);
                  echo_dev = make_dev(&echo_cdevsw, 0, UID_ROOT, GID_WHEEL,
                      0600, "echo");
                  uprintf("Echo driver loaded.
");
                  break;
          case MOD_UNLOAD:
                  destroy_dev(echo_dev);
                  free(echo_message, M_ECHO);
                  uprintf("Echo driver unloaded.
");
                  break;
          default:
                  error = EOPNOTSUPP;
                  break;
          }

          return (error);
  }

  DEV_MODULE(echo, echo_modevent, NULL);

This driver declares and defines a new malloc_type structure named M_ECHO. To use this malloc_type structure, malloc and free are adjusted accordingly.

Note

Because M_ECHO is used only locally, MALLOC_DECLARE is unnecessary—it’s only included here for demonstration purposes.

Now that Example 2-1 uses a unique malloc_type structure, we can easily profile its dynamic memory usage, like so:

$ sudo kldload ./echo-2.0.ko
Echo driver loaded.
$ vmstat -m | head -n 1 && vmstat -m | grep "echo_buffer"
         Type InUse MemUse HighUse Requests  Size(s)
  echo_buffer     1     1K       -        1  512

Notice that Example 2-1 requests 512 bytes, though sizeof(echo_t) is only 260 bytes. This is because malloc rounds up to the nearest power of two when allocating memory. Additionally, note that the second argument to MALLOC_DEFINE (echo_buffer in this example) is used in the output of vmstat (instead of the first argument).



[2] M_TEMP is defined in /sys/kern/kern_malloc.c.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.176.194