Skip Navigation Links | |
Exit Print View | |
Device Driver Tutorial Oracle Solaris 11.1 Information Library |
1. Introduction to Device Drivers
3. Reading and Writing Data in Kernel Memory
Writing Quote Of The Day Version 2
Opening the Device, Closing the Device, and Getting Module Information
Quote Of The Day Version 2 Source
Building, Installing, and Using Quote Of The Day Version 2
Modifying Data Stored in Kernel Memory
Writing Quote Of The Day Version 3
Attaching, Allocating Memory, and Initializing a Mutex and a Condition Variable
Checking for Changes, Cleaning Up, and Detaching
Allocating and Freeing Kernel Memory
Managing Thread Synchronization
Locking Rules for Quote Of The Day Version 3
Lock and Condition Variable Members of the State Structure
Creating and Destroying Locks and Condition Variables
Reporting and Setting Device Size and Re-initializing the Device
Quote Of The Day Version 3 Source
Building and Installing Quote Of The Day Version 3
Using Quote Of The Day Version 3
Exercising the Driver's I/O Controls
The pseudo device driver presented in this section writes a constant string to a system log when the driver is loaded.
This first version of the Quote Of The Day driver (qotd_1) is even more simple than the dummy driver from the previous chapter. The dummy driver includes all functions that are required to drive hardware. This qotd_1 driver includes only the bare minimum functions it needs to make a string available to a user command. For example, this qotd_1 driver has no cb_ops(9S) structure. Therefore, this driver defines no open(9E), close(9E), read(9E), or write(9E) function. If you examine the dev_ops(9S) structure for this qotd_1 driver, you see that no getinfo(9E), attach(9E), or detach(9E) function is defined. This driver contains no function declarations because all the functions that are defined in this driver are declared in the modctl.h header file. You must include the modctl.h header file in your qotd_1.c file.
This qotd_1 driver defines a global variable to hold its text data. The _init(9E) entry point for this driver uses the cmn_err(9F) function to write the string to a system log. The dummy driver also uses the cmn_err(9F) function to display messages. The qotd_1 driver is different from the dummy driver because the qotd_1 driver stores its string in kernel memory.
Enter the source code shown in the following example into a text file named qotd_1.c.
Example 3-1 Quote Of The Day Version 1 Source File
#include <sys/modctl.h> #include <sys/conf.h> #include <sys/devops.h> #include <sys/cmn_err.h> #include <sys/ddi.h> #include <sys/sunddi.h> #define QOTD_MAXLEN 128 static const char qotd[QOTD_MAXLEN] = "Be careful about reading health books. \ You may die of a misprint. - Mark Twain\n"; static struct dev_ops qotd_dev_ops = { DEVO_REV, /* devo_rev */ 0, /* devo_refcnt */ ddi_no_info, /* devo_getinfo */ nulldev, /* devo_identify */ nulldev, /* devo_probe */ nulldev, /* devo_attach */ nulldev, /* devo_detach */ nodev, /* devo_reset */ (struct cb_ops *)NULL, /* devo_cb_ops */ (struct bus_ops *)NULL, /* devo_bus_ops */ nulldev, /* devo_power */ ddi_quiesce_not_needed, /* devo_quiesce */ }; static struct modldrv modldrv = { &mod_driverops, "Quote of the Day 1.0", &qotd_dev_ops}; static struct modlinkage modlinkage = { MODREV_1, (void *)&modldrv, NULL }; int _init(void) { cmn_err(CE_CONT, "QOTD: %s\n", qotd); return (mod_install(&modlinkage)); } int _info(struct modinfo *modinfop) { return (mod_info(&modlinkage, modinfop)); } int _fini(void) { return (mod_remove(&modlinkage)); }
Enter the configuration information shown in the following example into a text file named qotd_1.conf.
Example 3-2 Quote Of The Day Version 1 Configuration File
name="qotd_1" parent="pseudo" instance=0;
Compile and link the driver. Use the -D_KERNEL option to indicate that this code defines a kernel module. The following example shows compiling and linking for a 32-bit architecture using the Oracle Solaris Studio C compiler:
% cc -D_KERNEL -c qotd_1.c % ld -r -o qotd_1 qotd_1.o
Note that the name of the driver, qotd_1, must match the name property in the configuration file.
Make sure you are user root when you install the driver.
Copy the driver binary to the /tmp directory as discussed in Device Driver Testing Tips.
# cp qotd_1 /tmp # ln -s /tmp/qotd_1 /usr/kernel/drv/qotd_1
Copy the configuration file to the kernel driver area of the system.
# cp qotd_1.conf /usr/kernel/drv
This qotd_1 driver writes a message to a system log each time the driver is loaded. The cmn_err(9F) function writes low priority messages such as the message defined in this qotd_1 driver to /dev/log. The syslogd(1M) daemon reads messages from /dev/log and writes low priority messages to /var/adm/messages.
To test this driver, watch for the message in /var/adm/messages. In a separate window, enter the following command:
% tail -f /var/adm/messages
Make sure you are user root when you load the driver. Use the add_drv(1M) command to load the driver:
# add_drv qotd_1
You should see the following messages in the window where you are viewing /var/adm/messages:
date time machine pseudo: [ID 129642 kern.info] pseudo-device: devinfo0 date time machine genunix: [ID 936769 kern.info] devinfo0 is /pseudo/devinfo@0 date time machine qotd: [ID 197678 kern.notice] QOTD_1: Be careful about reading health books. You may die of a misprint. - Mark Twain
This last line is the content of the variable output by the cmn_err(9F) function in the _init(9E) entry point. The _init(9E) entry point is called when the driver is loaded.