Most of the abstract functionality that is needed in a kernel is already in the Linux kernel. Linux has one of the best-designed buffer caches of any Unix-like operating system. A few things are left to be completed in the memory management and in the networking layer, but as more and more development is done, it seems (and reasonably so) that there are fewer and fewer projects that can be done by people with little operating systems knowledge and experience. Those who know enough to know what needs to be done with the memory management don't need to read documentation on how the kernel works; many of them find it faster to simply read the Linux source code.
That is not to say that there = are few projects in the Linux community that beginners can do; there are very many, but most of these projects are not within the kernel itself.
One project that relative beginners can accomplish, and which will never go out of fashion, is writing device drivers for new hardware. There is still hardware that Linux does not support, new hardware is being released by manufacturers all the time, and Linux users buy hardware and then want to use it with Linux.
Fortunately, the interface used to write device drivers is relatively simple and clean. By clean, I mean that there are not many exceptions to the rules or little tricks you have to play to get things to work. Over the next few columns (few is relative, I could spend a few years at this...) I will cover the information you need to know to write various kinds of device drivers.
Some of this information is already in the Linux Kernel Hackers' Guide, but I will expand on the information here. When I write something new here, it will eventually find its way into the Kernel Hackers' Guide; this is one way that Linux Journal supports the Linux Documentation Project.
In an almost contradictory way, I'm to initiate this Kernel Korner column with a description of how (and when!) to implement a device driver as a user program.
The first rule of adding code to the Linux kernel is don't. The code that is in the kernel cannot be swapped, and therefore takes up precious memory whether it is being used at the time or not. Many hardware devices can be driven by user-space programs which are kept nicely out of the way (either swapped out or not running at all) when the device is not being used. One prime example of devices that are implemented this way are video cards.
While the Linux startup code has options to initialize the video modes for many different kinds of cards, the actual device support for video cards in the Linux kernel proper is extremely limited, and is comprised of support for putting text on the screen on either monochrome (hercules-style) or color (CGA, EGA, VGA, and above) cards. No support for graphics is included.
XFree86 provides user-level drivers for many graphics cards within the X servers. These are only loaded when the X servers are running, and parts that aren't being used at the moment can be swapped out when necessary. In addition, by not making the device use a system-call interface to write, these drivers are faster because they are implemented in user space.
There are, of course, drivers that cannot be written as user-space drivers: most commonly, hardware that requires a driver that can service interrupts. We'll deal with these in a future installment.
Perhaps the most common way that a device driver communicates with hardware (at least on the PC architecture) is through the I/O bus. This is a bus which is completely separate from the memory bus, and which is accessed with special machine instructions. For a concrete example, let's use the parallel port. The parallel port driver is in the kernel for three reasons: it can be interrupt-driven, it manages contention, and it has historically been part of the kernel. It's also reasonably small, and very common, so it doesn't bloat the kernel very much. However, the parallel port can be driven from user space. Let's look at how this could be done.
The parallel port has three addresses on the I/O bus, and they are specified by a base address and two offsets. This is common for devices; many devices have several base addresses to choose from, and any other ports that are used are specified as offsets from the base. The three base addresses for the parallel port are given in linux/lp.h, and are (in hex) Ox3bc, Ox378, and Ox278. The status port is the next port above that, and the control port is above the status port. So if the base I/O port, to which characters are written, is Ox378, then the status port is Ox379 and the control port is Ox380.
Perhaps the most common way that a device driver communicates with hardware... is through the 1/0 bus.
You need enough documentation for a device to know how to talk to it. The 8255 chip is the chip that the parallel port is based on, and the documentation for that chip and for the parallel port interface describes the three ports.
The status port can report several conditions when it is read:
If 0, printer is busy
If 0, printer has ACKnowledged the character sent
If 1, printer is out of paper
If 1, printer is on-line
If 0, printer has in an error condition
The control port controls several things when it is written:
Set to 1 to enable sending interrupts when the printer is ready
Set to 1 to tell printer ready to talk
Set to O to tell printer to initialize itself
Set to 1 to prepare to send another byte to printer
Unfortunately, not all printers agree about all the signals that can be sent, so the least common denominator has to be used. This means that I won't use all of the bits you see in the tables. Also, I obviously won't use the interrupt-enable bit, since interrupts can't be used from user-level programs.
I'm also not going to do any serious error detection; I want to show how simple it can be to write a simple driver that works (more or less). If you want to see how error detection could be handled, simply read include/linux/lp.h and drivers/char/lp.c in the Linux kernel source.
The program userlp.c (see sidebar) needs to be compiled with optimization fumed on and run as root (or setuid root) to work. It takes a file from the standard input and prints it to the printer specified on the command line: O, 1, or 2, corresponding to lpO, lpi, and lp2, respectively.
This has only been lightly tested on one printer, unlike the standard kernel driver, so I can't say that it will work on your printer. This doesn't matter, because this is only an example. Note that I could have written the same driver as a /bin/sh script that used /dev/port and dd, and probably done it in less time, but you are more likely to be writing a device driver in C than in /bin/sh.
Practical Task Scheduling Deployment
July 20, 2016 12:00 pm CDT
One of the best things about the UNIX environment (aside from being stable and efficient) is the vast array of software tools available to help you do your job. Traditionally, a UNIX tool does only one thing, but does that one thing very well. For example, grep is very easy to use and can search vast amounts of data quickly. The find tool can find a particular file or files based on all kinds of criteria. It's pretty easy to string these tools together to build even more powerful tools, such as a tool that finds all of the .log files in the /home directory and searches each one for a particular entry. This erector-set mentality allows UNIX system administrators to seem to always have the right tool for the job.
Cron traditionally has been considered another such a tool for job scheduling, but is it enough? This webinar considers that very question. The first part builds on a previous Geek Guide, Beyond Cron, and briefly describes how to know when it might be time to consider upgrading your job scheduling infrastructure. The second part presents an actual planning and implementation framework.
Join Linux Journal's Mike Diehl and Pat Cameron of Help Systems.
Free to Linux Journal readers.Register Now!
- SUSE LLC's SUSE Manager
- My +1 Sword of Productivity
- Murat Yener and Onur Dundar's Expert Android Studio (Wrox)
- Managing Linux Using Puppet
- Non-Linux FOSS: Caffeine!
- Doing for User Space What We Did for Kernel Space
- Tech Tip: Really Simple HTTP Server with Python
- SuperTuxKart 0.9.2 Released
- Parsing an RSS News Feed with a Bash Script
- Rogue Wave Software's Zend Server
With all the industry talk about the benefits of Linux on Power and all the performance advantages offered by its open architecture, you may be considering a move in that direction. If you are thinking about analytics, big data and cloud computing, you would be right to evaluate Power. The idea of using commodity x86 hardware and replacing it every three years is an outdated cost model. It doesn’t consider the total cost of ownership, and it doesn’t consider the advantage of real processing power, high-availability and multithreading like a demon.
This ebook takes a look at some of the practical applications of the Linux on Power platform and ways you might bring all the performance power of this open architecture to bear for your organization. There are no smoke and mirrors here—just hard, cold, empirical evidence provided by independent sources. I also consider some innovative ways Linux on Power will be used in the future.Get the Guide