Go to the previous, next section.

Printer Spooler

Spooler Introduction

The Printer Spooler enables the printer to be shared among multiple processes. This allows each process to see a virtual printer which it can print to and also allows a process to submit a file for printing. It can be used by both native tasks and by virtual tasks via the `vprinter' module.

Spooler Operation

When a file is submitted for printing, its name is added to a list. A separate process processes this list in order to print the files. The list is processed in a FIFO (First In First Out) fashion. Although scheduling algorithms are available including SJF (Shortest Job First) and LJF (Longest Job First), a FIFO system was used in order to maintain simplicity and functionality. A virtual printer can also be opened allowing a process to print to a file when it doesn't know how much is to be printed. When the file is closed, it is added to the list. This is used by the `vprinter' module for emulating printer ports.

When the thread handling the printing of files is initially created, it looks in the spool directory and if there are any files there it automatically adds them to the list. The spool directory is defined in the header file `<vmm/spooler.h>' and is by default set to spool.

Because of the dual access to the spool list by both the thread adding a spool file and the thread processing the spool list, access to the list is protected by a semaphore.

Spooler Functions

Adding A File To The Spooler

If a process wishes to write its output to a file and then submit the file to be printed it can use the new_spool_file function to generate a unique file name.

spooler Function: void new_spool_file (char *fname)

This function allows a process to obtain a unique name for use in creating temporary files in the spool directory. fname is a buffer into which the new name is written and should be able to hold a string of length MAX_SPOOL_NAME characters. This function does not return a value.

A process can add a file to the spooler using the add_spool_file function. This is a single call with nothing further being required.

spooler Function: bool add_spool_file (char *fname)

This function allows a process to submit a file to be printed by the spooler. fname is the name of the file to be printed. The spooler makes a copy of this file in the spool directory with a unique filename and adds it to the list of files to be printed. This returns TRUE if the file was spooled successfully or FALSE if an error occurred.

Using The Spooler As A Printer

To use the spooler as if it were a virtual printer, a process open's the spool file to obtain a handle, writes to the file and then closes the file to have the data printed. The process can optionally discard the data it has written to the file.

spooler Function: int open_spool_file (char *name)

This function opens a spool file allowing a processing to write to the printer via a handle. name is the name that will appear in the spool list and is used as an identifier so that the user can keep track of the file in the spool list. This returns -1 if an error occurred otherwise a handle to be used for other operations.

spooler Function: void close_spool_file (int handle)

This function closes a spool file and adds it to the list of files to be printed. handle is the handle that was returned by a previous call to the function open_spool_file. This function does not return a value.

spooler Function: void discard_spool_file (int handle)

This function closes a file but discards the file instead of adding it to the list of files to be printed. This allows a process to gracefully cleanup whilst not wanting any output to go to the printer. handle is the handle that was returned by a previous call to the function open_spool_file. This function does not return a value.

spooler Function: void write_spool_file (int handle, char *data, int len)

This function allows a process to write data to the spool file. handle is the handle that was returned by a previous call to the function open_spool_file. data is the data to be written to the spool file. It may contain any data or characters. len is the len of data that is to be written to the spool file. This function does not return a value.

Example Function Usage

The simplest way for a process to print a file already on disk is to use the add_spool_file function.

#include <vmm/spooler.h>

...

/* add the file named `output' to the spool */
if(spooler->add_spool_file("output")) {

    /* function succeeded */
    ...

} else {

    /* function failed */
    ...

}

To create a unique file name to use for a spool file, use the new_spool_file function.

#include <vmm/spooler.h>

...

char fname[MAX_SPOOL_NAME];

/* obtain a unique filename */
spooler->new_spool_name(fname);

To use the spooler as a virtual printer, use the open_spool_file, write_spool_file and close_spool_file functions.

#include <vmm/spooler.h>

...

/* open a spool file, write to it, then close it */
static char data[] = "Test string";
int handle;

if((handle = open_spool_file("test")) != -1) {
    spooler->write_spool_file(handle, data,
                              sizeof(data));
    spooler->close_spool_file(handle);
}

To discard the printer output instead of printing it, use the discard_spool_file function.

#include <vmm/spooler.h>

...

/* open a spool file, write to it, then discard
   the output from it */

static char data[] = "Test string";
int handle;

if((handle = open_spool_file("test")) != -1) {
    spooler->write_spool_file(handle, data,
                              sizeof(data));
    spooler->close_spool_file(handle);
}

Go to the previous, next section.