A Quick Introduction to UNIX Coding


Introduction

This document was written in 1998 to introduce University of Waterloo ECE 450 students to functions in UNIX which would be necessary to write the course project, a very basic Real Time Executive. More information on each of the commands can be found in the man pages. Each section begins with the name of the command, the function's prototype and a list of the libraries that must be included in order for your to call the function. The following table summarizes each of the commands explained and provides a link to the explanation in this document.

Function Explanation
kill( pid, sig ) sends a signal number "sig" to process number "pid"
shmget( key, size, flag ) gets/creates a shared memory buffer
shmctl( id, cmd, buff ) controls a shared memory buffer
shmat( id, address, flag ) attaches shared memory to a child process' data segment
getpid() returns the process id
fork() spawn a child process
execl( path, args... ) overlays a process with another executable
usleep( time ) causes a process to sleep for at least "time" microseconds
setjmp( buff ) stores a system's running information into "buff"
longjmp( buff, return ) restores a system's running information from "buff"

Back to the top


Kill

     #include <sys/types.h>
     #include <signal.h>

     int kill(pid_t pid, int sig);

This function sends a signal to a process with process id pid. The signals which can be sent are declared in the signal.h file. The function returns 0 when successful and -1 when it fails. The sample code below would be the equivalent of pressing ctrl-C on the keyboard.

   pid_t pid;

   pid = getpid();
   kill( pid, SIGQUIT );

Back to the top


Get Shared Memory

     #include <sys/types.h>
     #include <sys/ipc.h>
     #include <sys/shm.h>

     int shmget(key_t key, int size, int shmflg);

This function gets the identifier for a block of shared memory. The block retrieved will be of size "size" and correspond to the shared memory block with the key "key". The "key" is some number which the programmer uses common throughout the code which wishes to access the shared memory block. A value of IPC_PRIVATE may be specified for the "key" parameter so that the operating system selects the next available key for a newly created shared block of memory.

Using different values for the flag "shmflg" gives control on how the shared memory block is retrieved. A value of IPC_CREAT requires that the call to the function fails if the shared memory block is not new. This function returns the shared memory block identifier, or -1 in the case of failure.

   int smem, smem2;

   smem = shmget( IPC_PRIVATE, 100, 0 );
   smem2 = shmget( 0x30, 100, IPC_CREAT );

Back to the top


Control Shared Memory

     #include <sys/types.h>
     #include <sys/ipc.h>
     #include <sys/shm.h>

     int shmctl(int shmid, int cmd, struct shmid_ds *buf);

This function controls a shared memory block. The first parameter is a shared memory id which is obtained via the shmget function. The second parameter specifies what is to be done to the block of shared memory. The "buf" parameter provides a place for information to be returned if the "cmd" requires it. A summary of the commands follows.

IPC_STAT - gives status information about the block
IPC_SET - change control information like permissions and ownership
IPC_RMID - remove a shared memory id and block
Other commands exist but require super-user privileges to execute. Function returns 0 upon success and -1 on failure.

   int smem;

   smem = shmget( IPC_PRIVATE, 100, 0 );
   shmctl( smem, IPC_RMID, NULL );         // deletes sh mem block

Back to the top


Shared Memory Attach

     #include <sys/types.h>
     #include <sys/ipc.h>
     #include <sys/shm.h>

     void *shmat(int shmid, void *shmaddr, int shmflg);

This function attaches a void * pointer to a shared memory block. This gives a process local access to a shared memory block as if it were any other block of memory. The block that is attached is identified using the shared memory identifier "shmid". The "shmaddr" and "shmflg" parameters are used for indicating specific memory locations for the attachment to occur at, and typically are not necessary. This function returns a pointer to the location which was attached to, or -1 for failure.

   int smem;
   void *my_mem;

   smem = shmget( IPC_PRIVATE, 100, 0 );
   my_mem = shmat( smem, 0, 0 );

Back to the top


Get Process Id

     #include <sys/types.h>
     #include <unistd.h>

     pid_t getpid(void);

This function returns the process id of the executing process. A value of -1 is returned in the case of failure.

   pid_t pid;

   pid = getpid();

Back to the top


Fork

     #include <sys/types.h>
     #include <unistd.h>

     pid_t fork(void);

This function creates a child process which is an exact copy of the parent process. The return value of this function is the process id of the child which was spawned if the process getting the return is the parent, 0 if the process is the child, or -1 in the case of failure. The different return code for parent and child allows for code to identify whether it is the parent or child process. Quite often an execl call is made to replace the child process.

   pid_t pid;

   pid = fork();
   if( pid == 0 )
   {
      // only the child should get here
      while( 1 )
         printf( "I am the child\n" );
   } // end if

   // only the parent should get here

Back to the top


Execute

     #include <unistd.h>

     int execl(const char *path, const char *arg0, ...,
          const char *argn, char * /*NULL*/);

This function overlays the current process with another executable piece of code. The "path" specifies the name of the executable to be run, "arg0" is traditionally the name of the executable called, and the remaining parameters are a variable length list of strings which are passed to the overlayed code. The end of this list is denoted by a NULL. This function only returns if something failed since the process should be overlayed. If the function returns it gives a value of -1.

   pid_t pid;
 
   pid = fork();
   if( pid == 0 )
      execl( "keyboard", "keyboard", 0 );  // run the keyboard executable
      

Back to the top


Micro-Sleep

     #include <unistd.h>

     int usleep(unsigned int useconds);

This function suspends the current process for a value of "useconds" micro seconds. Execution resumes from the function call when the time has passed.

   printf( "wake me up in a second\n" );
   usleep( 1000000 );
   printf( "I woke up!\n" );

Back to the top


Set Jump

     #include <setjmp.h>

     int setjmp(jmp_buf env);

This function stores the system information in the buffer "env". This function returns a zero if it is returning from a storage call. The longjmp function is used to restore the system information, thus returning it to the setjmp call. The function returns a non-zero value specified in the longjmp call when the it is being returned to from the longjmp call.

   jmp_buf env;

   if( setjmp( env ) == 0 )
		printf( "environment stored\n" );
   else
      printf( "jumped back!\n" );

Back to the top


Long Jump

     #include <setjmp.h>

     void longjmp(jmp_buf env, int val);

This function is used to restore the environment stored in "env" by a setjmp call. The value in "val" specifies the return code to be returned by the setjmp function which will be jumped to when the environment is restored. A non-zero value must be specified for "val". If zero is specified for "val" the return code to setjmp will be 1.

   jmp_buf env;

   if( setjmp( env ) == 0 )
		printf( "environment stored\n" );
   else
      printf( "jumped back!\n" );
   
   .
   .
   .
   
   longjmp( env, 1 );

Back to the top