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.
#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.
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.