The most substantive part of the manual describes how to write C code, covering things like formatting the code, comments, how to use C cleanly, how to name your functions and variables, and how to declare, or not declare, standard system functions that you wish to use.
Code formatting is a religious issue; many people have different styles that they prefer. I personally don't like the FSF's style, and if you look at gawk, which I maintain, you'll see it's formatted in standard K&R style. But this is the only variation in gawk from this part of the coding standards (other variations will go away in gawk 3.0, coming this year).
Nevertheless, while I don't like the FSF's style, I consider it of the utmost importance, when modifying some other program, to stick to the coding style already used. Having a consistent coding style is more important than which coding style you pick.
What I find important about the chapters on C coding is that the advice is good for any C coding, not just if you happen to be working on a GNU project. So, if you're just learning C, or even if you've been working in C (or C++) for a while, I would recommend these chapters to you, since they encapsulate many years of experience.
Two chapters cover writing documentation for your program. The preferred way is to write a manual using Texinfo, which was discussed in an earlier column (Issue #6, October 1994). There is some nice advice in here about writing manuals. And, as described earlier, Texinfo is an enjoyable language in which to write documentation.
Finally, there are three chapters devoted to the mechanics of making a release. These chapters discuss the conventions to use for Makefiles, how configuration should work, and other generalities about how a release should work.
These chapters, together with the Autoconf manual, provide the needed information for packaging up a program and making the final released tar] file.
We'll take a look now at the chapter entitled Program Behavior for All Programs. This chapter provides the principles of software design that make GNU programs better than their Unix counterparts. We will quote selected parts of the chapter, with some examples of where these principles have paid off.
Avoid arbitrary limits on the length or number of any data structure, including file names, lines, files, and symbols, by allocating all data structures dynamically. In most Unix utilities, “long lines are silently truncated”. This is not acceptable in a GNU utility.
This is perhaps the single most important rule in GNU software design, “no arbitrary limits.” All GNU utilities should be able to manage arbitrary amounts of data.
While this makes it harder for the programmer, it makes things much better for the user. I have one gawk user who runs an awk program on over 650,000 files (no, that's not a typo) to gather statistics. gawk grows to over 192 Megabytes of data space, and the program runs for around seven CPU hours. He would simply not be able to run his program using another awk implementation.
Utilities reading files should not drop NUL characters, or any other nonprinting characters (including those with codes above 0177). The only sensible exceptions would be utilities specifically intended for interface to certain types of printers that can't handle those characters.
It is also well known that Emacs can edit any arbitrary file, including files containing binary data!
Check every system call for an error return, unless you know you wish to ignore errors. Include the system error text (from perror or equivalent) in every error message resulting from a failing system call, as well as the name of the file if any and the name of the utility. Just “cannot open foo.c” or “stat failed” is not sufficient.
Checking every system call provides robustness. This is another case where life is harder for the programmer, but better for the user. An error message detailing what exactly went wrong makes finding and solving any problems much easier.
Check every call to malloc or realloc to see if it returned zero. Check realloc even if you are making the block smaller; in a system that rounds block sizes to a power of 2, realloc may get a different block if you ask for less space.
In Unix, realloc can destroy the storage block if it returns zero. GNU realloc does not have this bug: if it fails, the original block is unchanged. Feel free to assume the bug is fixed. If you wish to run your program on Unix, and wish to avoid lossage in this case, you can use the GNU malloc.
You must expect free to alter the contents of the block that was freed. Anything you want to fetch from the block, you must fetch before calling free.
In three short paragraphs, Richard Stallman has distilled the important principles for doing dynamic memory management using malloc. It is the use of dynamic memory, and the “no arbitrary limits” principle that makes GNU programs so robust and more capable than their Unix counterparts.
Use getopt_long to decode arguments, unless the argument syntax makes this unreasonable.
Long options were mentioned earlier. Their use is intended to make GNU programs easier to use and more consistent than the Unix versions. The getopt_long function is a nice one; it provides you all the flexibility and capabilities you may need for argument parsing. As a simple yet obvious example, --verbose is spelled exactly the same way in all GNU programs. Contrast this to -v, -V, -d etc.
Finally, we'll quote from an earlier chapter that discusses how to write your program differently than the way a Unix program may have been written.
For example, Unix utilities were generally optimized to minimize memory use; if you go for speed instead, your program will be very different. You could keep the entire input file in core and scan it there instead of using stdio. Use a smarter algorithm discovered more recently than the Unix program. Eliminate use of temporary files. Do it in one pass instead of two (we did this in the assembler).
Or, on the contrary, emphasize simplicity instead of speed. For some applications, the speed of today's computers makes simpler algorithms adequate. Or go for generality. For example, Unix programs often have static tables or fixed-size strings, which make for arbitrary limits; use dynamic allocation instead. Make sure your program handles NULs and other funny characters in the input files. Add a programming language for extensibility and write part of the program in that language.
An excellent example of the difference an algorithm can make is GNU diff. My computer's previous incarnation was an AT&T 3B1; a system with a MC68010 processor, a whopping two megabytes of memory and 80 megabytes of MFM disk.
I did (and do) lots of editing on the manual for gawk, a file that is currently over 17,000 lines long (although at the time, it was only in the 10,000 lines range). I used to use diff -c quite frequently to look at my changes. On this slow system, switching to GNU diff made an extremely noticeable difference in the amount of time it took for the context diff to appear. The difference is almost entirely due to the better algorithm that GNU diff uses.
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!
- SourceClear Open
- SUSE LLC's SUSE Manager
- My +1 Sword of Productivity
- Tech Tip: Really Simple HTTP Server with Python
- Murat Yener and Onur Dundar's Expert Android Studio (Wrox)
- Managing Linux Using Puppet
- Non-Linux FOSS: Caffeine!
- Stunnel Security for Oracle
- Doing for User Space What We Did for Kernel Space
- Google's SwiftShader Released
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