If you're in a university computer science program, it is likely that you will be required to take some courses relating to operating systems. In a more advanced
course, the MINIX operating system may be used as an example, and you may be assigned projects that involve creating new system calls and system commands--
modifying and adding to the source code. I recently completed such a course, so I know how difficult it can be to know where to begin. I can't say I'm an OS
expert, but hopefully this can guide you in the right direction.
A system call is a function that allows a user program to communicate with the OS. An example of an existing system call on UNIX-based systems is chmod. (So that
you aren't confused, I should note that it is also a system command.) In C, the chmod system call would be made thus:
if (chmod("/home/al-kahina/secrets.txt", S_IRUSR|S_IWUSR) != 0) {
printf("chmod error: %s (%d)\n", strerror(errno), errno);
return 1;
}
If an error does not occur, this will result in the file /home/al-kahina/secrets.txt being given the permissions 0600, which means that the owner of the file may
read and write but not execute the file and everyone else has no access to the file.
In an OS course project, you may be asked to create a system call that can be used in a similar way. You will need to modify the source code thus, assuming your
system call is called sys_call (also, unless otherwise stated, all your code will be in C):
-
Create these files:
-
An assembly-language file called sys_call.S under the /usr/src/lib/libc/syscall/ directory. Part of the MINIX system is in assembly language, so this is
necessary to act as a glue between the assembly-language parts and the C-language parts. This may seem daunting, but this is actually very easy. Take a
look at the other assembly-language files for other system calls in the same directory, replace their call names with sys_call, and you're done. Remember
to add an entry for it in Makefile.inc in the same directory.
-
A file called _sys_call.c under the /usr/src/lib/libc/posix/ directory. It will have a function in it called sys_call that does very little work except
for populating the message structure, making the actual system call, and possibly checking its return value to determine what to return. Again, look to
the files of existing system calls in the directory for guidance. Remember to add an entry for it in Makefile.inc in the same directory.
-
Depending on what the system call is doing, you may not have to create a separate file for the system call function that does the actual work. However,
if there does not already exist a file of system call functions under the appropriate server for system calls related to yours, you may want to create a
separate file under the appropriate server in /usr/src/servers/[server]/. It can be called whatever you want, though preferably it should be something
related to what your system call does. Inside this file, you will write a function called do_sys_call that does the actual work. It will read values from
the message structure that was populated inside your sys_call function over in _sys_call.c--the structure will be called m_in. Don't worry about
populating errno for errors; whatever value is returned from this function will be the value of errno. If you implement do_sys_call in a separate file,
remember to add an entry for it in the server's Makefile.
-
Modify these files:
-
If you do not make a separate file for the do_sys_call function, implement it in the appropriate file under /usr/src/servers/[server]/ as detailed above.
For example, if you are making a system call that manipulates a file's permission bits, put it in protect.c (which is where do_chmod and do_chown are).
-
A prototype for the sys_call function in unistd.h under the /usr/src/include/ directory.
-
A prototype for the do_sys_call function in proto.h under the /usr/src/servers/[server]/ directory.
-
A call number called SYS_CALL in callnr.h under the /usr/src/include/minix/ directory. Be sure that the number you use is not being used by another
system call, which will be easy to verify as all the system call number macros should be in this file.
-
An entry for do_sys_call in the call vector in table.c under the /usr/src/servers/[server]/ directory. It is very important that the position of the entry
corresponds to its call number; this should not be difficult as there are comments next to each entry indicating the position. Also, you may have to add
a comment next to the corresponding no_sys entries under other servers' table.c files if they share a call vector. For example, the pm and vfs servers
share a call vector, so if you add do_sys_call to pm/table.c in the 69th position of the call vector, change the comment next to the 69th position in
vfs/table.c indicating that the position has been taken.
-
If the system call requires new global variables, glo.h under /usr/src/servers/[server]/ is a good place to put them.
-
If you add new global variables or new members to existing structures and they require initialization, a good place to initialize them is before the
infinite loop in the main function of main.c under the /usr/src/servers/[server]/ directory.
There may be other things you'll need to add depending on what sys_call does, but this is a general list of things to add to the source code. Keep in mind that
it may be more complicated in certain circumstances. For example, if a system call is meant to manipulate the protection bits of a file, there will need to be
a do_sys_call function somewhere under the vfs directory and an fs_sys_call function under the mfs directory, and mfs has a separate call vector to deal with as
well. For cases like that, and whenever in doubt, use existing system calls that do similar things as examples.
System commands can be called from the command line, often with parameters. An example of this is ls, which lists the contents of a directory. They do not
necessarily have to communicate with the OS, but most do, and if you are assigned a project involving creating a system command, it probably will be requesting
a service from the OS. You will probably be required to make a system call to do the actual work. After you create the system call like above, it is very simple
to wrap it in a system command. The system command is created thus, assuming your system command is called sys_command:
-
Create a directory called sys_command under /usr/src/commands/.
-
Create a Makefile under the /usr/src/commands/sys_command/ directory. Use the Makefiles of other system commands as examples.
-
Create a file called sys_command.c under the /usr/src/commands/sys_command/ directory. This is where you will implement the system command, though most of
the work will likely be done by system calls. This program will mainly handle the parameters, make the system calls, and handle their return values.
-
Remember to add an entry for sys_command in the Makefile under the /usr/src/commands/ directory.
And that's it! If you follow the example of other system commands, when MINIX is recompiled, the sys_command executable will be created in the /bin/ directory
with the other system commands, and you will be able to use it from the command line.
Last updated May 7, 2016
al-Kahina CLI Programs Home