Operating Systems

Project #1 Adding a System Call

Purpose:

 

        Through this project, we expect that students can expand their vision from user-space programs to the deeper place which is the interface between user-space programs and the operating system, i.e. system calls. Students will learn the mechanism of system call and the real-world implementations in Linux and FreeBSD. In the future, we will go deeper into the kernel, and that is the project #2, adding a kernel module.

 

Background:

 

        The interface between the operating system and the user programs is defined by the set of “extended instructions” that the operating system provides. These extended instructions are known as system calls. The system calls create, delete, and use various software objects managed by the operating system. The most important objects are processes and files.

        User programs communicate with the operating system and request services from it by making system calls. Corresponding to each system call is a library procedure that user programs can call. This procedure puts the parameters of the system call in a specified place, such as the machine registers, and then issues a TRAP instruction (a kind of protected procedure call) to switch the CPU mode to the kernel mode. When the operating system gets control after the TRAP instruction, it examines the parameters to see if they are valid; and if so, it performs the work requested, i.e. invoking the system call. The purpose of the library procedure is to hide the details of the TRAP instruction and make system calls look like ordinary procedure calls.

        Take the sys_read() system call in Linux as an example. Its corresponding library procedure is read(), which has three parameters, the first one specifying the file to be read, the second one specifying a buffer to put the file’s data, and the third one telling how many bytes to read. Its prototype is below:

        ssize_t read ( int fd, void *buf, size_t count );

 

The effect of calling the read() procedure (and thus making the sys_read() system call) is to cause data from the specified fd to be copied into the buf, where the program can get from it. The procedure returns the number of bytes actually read. This value is normally the same as count, but may be smaller, if, for example, the end-of-file is encountered while reading.

        If the system call cannot be carried out, either due to an invalid parameter or a disk error, the return value is set to –1, and the error number is put in a global variable, where the program can inspect it. Programs should always check the results of their system calls to see if errors occurred.

 

General steps to add a system call in Linux and FreeBSD:

 

What needs to be done ?

- assign an id to the system call

- make the kernel aware of the system call

- allow user programs to use the system call

 

Linux version :

 

        Step 1.        assign an id to your system call

                        - /usr/src/linux/include/asm-i386/unistd.h

        Step 2.        write source code of your system call

                        - /usr/src/linux/kernel/sys.c

        Step 3.        put include files written by yourself

                        - /usr/include/sys/ , /usr/include/linux/

        Step 4.        add an entry into system call table

                        - /usr/src/linux/arch/i386/kernel/entry.S

        Step 5.        rebuild the kernel image and install it

       

Step 6.        write a test program to test the system call

 

FreeBSD version :

 

        Step 1.        assign an id to your system call

                        - /sys/kern/syscalls.master    

                        ex. 364 STD BSD { int sys_myhello (char *buf); }

 

Step 2.    run "sh makesyscalls.sh syscalls.master" in /usr/src/sys/kern/

-         This will create three files: syscall.h, syscall-hide.h, and sysproto.h

-         Copy these three files to /usr/include/sys/

 

Step 3.    edit your file, says sys_myhello.c, in /usr/src/sys/kern/  to implement your system call sys_myhello().

                - Every system call is passed two parameters : 1. pointer to struct proc and 2. pointer to the user defined system call argument structure, which in our case is : sys_myhello_args. The structure sys_myhello_args should be defined by the implementor of the system call and should contain all the arguments to the system call. In our case it should have a pointer to char.
#include <sys/param.h>
#include <sys/systm.h>

                #include <sys/sysproto.h>

               

/* if you don’t include sysproto.h, then you must write this structure yourself.

struct syshello_args
{
char *buf;
};

*/


/* The system call itself should be implemented like this: */
int sys_myhello(p, uap)
struct proc* p; struct syshello_args* uap;
{
sprintf(uap->buf,"Hello"); /* fill the buffer with Hello */
p->p_retval[0] = 0; /* set the return value of the system call*/
return 0;
}

 

Step 4.    edit /sys/conf/files to add your file sys_myhello.c into it

 

Step 5.    make a new kernel and install it

 

Step 6.    write a test program to test the system call

       

Testing programs:

 

Linux version :

 

#include <stdio.h>
#include <linux/unistd.h>

 

static inline _syscall0( int , sys_myhello)        // note ‘_’ and no ‘;’

 

int main(int argc,char **argv)
{
        printf("return : %d\n", sys_myhello());
        return 0;
}
    

FreeBSD version :

 
#include <sys/syscall.h>
#include <unistd.h>
#include <stdio.h>
 
int     main(int argc, char **argv)
{
          if (argc != 2) {
            printf("%s yourname\n", argv[0]);
            exit(-1);
         }
         syscall(364, argv[1]);   

}

 

Assignment:

* Platform : Linux or FreeBSD

* Everyone must add a “Hello World” system call, which means a system call

 that print “Hello World” message to the console

* Any extra functionality will get some bonus

* Report: 60 %

* Implementation: 40 %

 

Deadline:

* Demo : 5/9-10 (Thursday and Friday 9AM-6PM) in 701 EECS Research Building

* Report : turn in when you demo

 

Report content:

* How system calls work on Linux or FreeBSD

  - What’s the instruction (Pentium CPU) that jumps to a previous defined location

in the kernel ?

  - Then, what the procedure at the location do ?

  - Besides, why we need the “blue” codes in the testing programs

* How to add a system call

* Describe your extra functions