[Return to Library] [Contents] [Previous Chapter] [Next Section] [Next Chapter] [Index] [Help]


11    Testing a Device Driver

After developing your device driver, you should produce the single binary module and then statically or dynamically configure it into the kernel. The chapters in Part 4 explain how to accomplish these tasks.

After your driver is statically or dynamically configured into the kernel, you should test it. One way to test a device driver is to write a test program. Implementing the test program involves the following tasks:

Each of these tasks is discussed in the following sections.


[Return to Library] [Contents] [Previous Chapter] [Next Section] [Next Chapter] [Index] [Help]


11.1    Writing the Test Program

The test program for the /dev/none device driver performs the following tasks:


The test program follows:

/***************************************************
 * testdevnone.c - Test program for /dev/none      *
 *                 driver                          *
 ***************************************************/
/***************************************************
 *                                                 *
 * Author: Digital Equipment Corporation           *
 *                                                 *
 ***************************************************/
/***************************************************
 *         INCLUDE FILES                           *
 *                                                 *
 ***************************************************/
/***************************************************
 *                                                 *
 *                                                 *
 * Header files required by testdevnone.c          *
 *                                                 *
 *                                                 *
 ***************************************************/

#include <stdio.h> #include <sys/ioctl.h> [1] #include <sys/file.h> #include <sys/limits.h> #include <io/ESA100/nonereg.h> [2]

char buf[100]; [3]

main() { int d; [4] int count; [5]

if((d = open("/dev/none",O_RDWR)) == -1) [6] { perror("/dev/none"); exit(1); }

ioctl(d,DN_GETCOUNT,&count); [7] printf("saw %d bytes\n",count); [8]

write(d,&buf[0],100); [9] printf("wrote 100 bytes\n"); [10]

ioctl(d,DN_GETCOUNT,&count); [11] printf("saw %d bytes\n",count); [12]

ioctl(d,DN_CLRCOUNT,&count); [13] printf("set count\n"); [14]

ioctl(d,DN_GETCOUNT,&count); [15] printf("saw %d bytes\n",count);

count = read(d,&buf[0],100); [16] printf("was able to read %d bytes\n",count); [17]


exit(0); [18] }

  1. Includes the ioctl.h header file because the test program uses the DN_GETCOUNT and DN_CLRCOUNT ioctl macros defined in the device register header file nonereg.h. Section 5.1.2 discusses these macros. [Return to example]

  2. Includes the device register header file, which is discussed in Section 5.1.2. The directory specification adheres to the directory created in Section 14.1.1. The directory specification you make here depends on where you put the device register header file. [Return to example]

  3. Declares an array that contains 100 character elements. This array is used to store the 100 bytes written by the nonewrite interface. [Return to example]

  4. Declares a variable to contain the return from the open system call. [Return to example]

  5. Declares a variable to store the character count. [Return to example]

  6. Calls the open system call, which in this example opens the device for read/write operations.

    The example passes two arguments:

    If the open system call executes successfully, it opens the device and returns a nonnegative value to the test program. However, if the system call fails, the kernel (in cooperation with the driver's noneopen interface) will have set the global variable errno to a constant value that describes the error. If an error occurs, the test program prints the error, using the perror interface, and quits. [Return to example]

  7. After the device is opened, gets the initial character count that was written to it. Although the count should be zero, it may not be if other users have already written data to the device.

    Remember that the noneioctl interface in the driver is used to read or clear the count of characters written to /dev/none. Here, the ioctl system call is used to read the count of characters written to the device. The kernel notices that the file associated with the descriptor d is actually a special file, looks up its ioctl interface in the dsent table, and invokes the driver's noneioctl interface. The kernel copies the return value from noneioctl back to the count variable defined in the test program because the bitmask for DN_GETCOUNT instructs it to do so. [Return to example]

  8. Calls the printf interface to display on the console terminal a message that indicates the number of bytes. [Return to example]

  9. Writes 100 bytes of data to /dev/none. The kernel invokes nonewrite because the file descriptor d is associated with a special file. The nonewrite interface counts these characters. [Return to example]

  10. Calls the printf interface to display on the console terminal a message that indicates that nonewrite wrote 100 bytes. [Return to example]

  11. Reads the count of characters written to the device now. The count should be 100 higher than it was in the previous section of code. The noneioctl interface is used exactly the same as it was to get the initial count. [Return to example]

  12. Calls the printf interface to display on the console terminal the number of bytes. [Return to example]

  13. Clears the count of characters written to the NONE device. The DN_CLRCOUNT macro accomplishes this task. This time, no data is returned by the device driver, so the kernel does not copy any data back to the test program. All three arguments are passed to the ioctl system call for the sake of correctness. When this ioctl call returns, the test program expects the current count to be the value zero (0). [Return to example]

  14. Calls the printf interface to display the message ``set count'' on the console terminal. [Return to example]

  15. To determine if the previous code cleared the count to zero (0), the test program reads the characters from the NONE device again. The printf interface is used to display the count. [Return to example]

  16. One design goal for the /dev/none device driver is that it should always return EOF on read operations. The test program checks this action by trying to read 100 bytes from the device. If the design goal was met, the read system call should return zero (0) bytes.


    The test program passes three arguments to the read system call:

    As discussed previously, the kernel notices that the file descriptor d is associated with a device and finds the dsent entry for the device's read interface, noneread. The kernel calls noneread to service the read request. The number of bytes successfully read is returned by the read system call. [Return to example]

  17. The printf interface prints the number of bytes that were read. [Return to example]

  18. The test program exits and the kernel automatically calls the noneclose interface. [Return to example]

The following shows the output from a sample run of the test program, which verifies that the driver is working correctly:

saw 0 bytes
wrote 100 bytes
saw 100 bytes
set count
saw 0 bytes
was able to read 0 bytes


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


11.2    Expanding the Test Program

You can expand the test program for the /dev/none device driver to do even more complete testing. For example, the test program could check the character count between each of several writes.

Because /dev/none is a simple driver, the test program is relatively straightforward. More complicated drivers require more complicated test programs, but the strategy is the same: for each interface you provide in the driver, test it independently from the other interfaces.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Chapter] [Index] [Help]


11.3    Tracking Problems in Testing

If the driver fails to behave as expected, you need to track down the problem and correct it. Use the following aids and hints:

Figure 11-1 shows the device driver testing worksheet for the /dev/none device driver. To identify the scope of your driver test program, use the device driver testing worksheet in Appendix C.

Figure 11-1: Testing Worksheet for /dev/none