Operating Systems, Spring 2002

Project #2: Adding a kernel module

INSTRUCTOR: Prof. Ying-Dar Lin, Email: ydlin@cis.nctu.edu.tw
       TAs: 1. I-Wei Chen(
陳一瑋), E-mail: iwchen@cis.nctu.edu.tw
               2. Yi-Hsiang Lin(
林逸祥), E-mail: yslin@cis.nctu.edu.tw

Purpose:

        In project #1, you have known how to add a system call, but the machine must be reboot for taking effect of new kernel.

In this project, you will know how the kernel can dynamically load functions only when they are needed by adding a kernel module.

 

Assignment:
* Platform : FreeBSD or Linux

* Adding a “hello” system call by using a kernel module
The output of executing “./hello Yourname” should be

[239] Hello! Yourname is 8823088!! Ret=8
Notes:
1. [239] “239” is the system call number

2. “Student ID” should be written in kernel module.

3. Return code should be the last digital of your student ID
(ex. 8823088 should return “8” )

* Any extra functionality will get some bonus

* Report: 50 %

* Implementation: 50 %

 

Report content:

1. What’s kernel modules? How its work on Linux or FreeBSD?

2. What can be implemented as modules? And what cannot?

3. How to add a kernel module?

4. Describe your extra functions.

Deadline:

* Demo : 6/20(Thu)pm6:00-11:00,6/21(Fri) pm1:00-6:00 at 701 EECS Research Building

* Report : turn in when you demo

General steps to add a module in FreeBSD and Linux:

FreeBSD:

1. edit /usr/share/examples/kld/syscall/module/syscall.c
#include <sys/types.h>

#include <sys/param.h>

#include <sys/proc.h>

#include <sys/module.h>

#include <sys/sysent.h>

#include <sys/kernel.h>

#include <sys/systm.h>

 

struct args

{

  char *buf;

};

 

static int

hello (struct proc *p, struct args *uap)

{

        char buf[128];

 

    printf ("Hello! Kernel!!\n");

    sprintf(buf,"Hello! Kernel!!", uap->buf); /* fill the buffer with Hello */
        strcpy(uap->buf, buf);

    p->p_retval[0] = 0; /* set the return value of the system call      */

 

    return 0;

}

 

static struct sysent hello_sysent = {

    1,          /* sy_narg */

    hello           /* sy_call */

};

 

static int offset = NO_SYSCALL;

 

 

static int load (struct module *module, int cmd, void *arg)

{

    int error = 0;

 

    switch (cmd) {

    case MOD_LOAD :

        printf ("syscall loaded at %d\n", offset);

        break;

    case MOD_UNLOAD :

        printf ("syscall unloaded from %d\n", offset);

        break;

    default :

        error = EINVAL;

        break;

    }

    return error;

}

 

SYSCALL_MODULE(syscall, &offset, &hello_sysent, load, NULL);

 

2.        product kernel module file: syscall.ko

% cd /usr/share/examples/kld/syscall/module

% make

 

Linux:

1. edit /usr/src/linux-2.4/arch/i386/kernel/entry.S

        .long SYMBOL_NAME(sys_hello)

 

2. edit /usr/src/linux-2.4/include/asm-i386/unistd.h

        #define __NR_hello              239

 

3. edit syscall.c

#include <linux/kernel.h>   /* We're doing kernel work */

#include <linux/module.h>   /* Specifically, a module */

#if CONFIG_MODVERSIONS==1

#define MODVERSIONS

#include <linux/modversions.h>

#endif

#include <sys/syscall.h>  /* The list of system calls */

#include <asm/uaccess.h>

extern void *sys_call_table[];

 

asmlinkage long our_sys_hello(char *name)

{

        char buf[128];

 

      sprintf(buf,"Hello! %s!!\n", name);

        strcpy(name,buf);

      printk("(our_sys_hello)Hello! Kernel!!\n");

      return 1;

}

 

/* Initialize the module - replace the system call */

int init_module()

{

  printk("init_module() starting\n");

  sys_call_table[__NR_hello] = our_sys_hello;

  return 0;

}

/* Cleanup - unregister the appropriate file from /proc */

void cleanup_module()

{

  printk("cleanup_module() finished\n");

}

 

4. edit Makefile(Notice: replace the kernel version ”2.4.18-3” as yours with “uname -r”)

# Makefile for a basic kernel module

CC=gcc

MODCFLAGS := -Wall -DMODULE -D__KERNEL__ -DLINUX -I/lib/modules/2.4.18-3/build/include

 

syscall.o:      syscall.c /usr/include/linux/version.h

                $(CC) $(MODCFLAGS) -c syscall.c

 

5. product kernel module file: syscall.o

% make

Testing programs:

FreeBSD:

 

1. edit hello.c

#include <stdio.h>

#include <sys/syscall.h>

#include <sys/types.h>

#include <sys/module.h>

 

int main(int argc, char **argv)

{

    char *endptr;

    int syscall_num;

    struct module_stat stat;

 

    if ( argc>1 )

    {

        stat.version = sizeof(stat);

        modstat(modfind("syscall"), &stat);

        syscall_num = stat.data.intval;

        syscall (syscall_num, argv[1]);

        printf("%s\n", argv[1]);

    }

}

 

2.    Loading kernel module

  % kldload ./syscall.ko

3.        Testing

% ./hello einstein

        Hello! einstein!!

 

 

 

 

 

 

 

Linux:

 

1. edit hello.c

#include <stdio.h>

#include <linux/unistd.h>

 

static inline _syscall1(int, hello, char *, buf)

 

int main(int argc, char **argv)

{

        if ( argc>1 )

        {

        printf("Before calling syscall hello(), argv[1]= %s\n", argv[1]);

        printf("return : %d\n", hello(argv[1]));

        printf("After calling syscall hello(), argv[1]= %s\n", argv[1]);

        return 0;

        }

}

 

2.    Loading kernel module

% insmod syscall.o

 

3.      Testing

% ./hello einstein

Hello! einstein!!