Slashdot Mirror


Linux System Programming

Jon Mitchell writes "As a Perl programmer recently thrown in to the world of C development on Linux, I have been looking for something that would take my K&R level of experience and bring it up to date with modern methods, hopefully letting me write more efficient and reliable programs. Linux System Programming is a volume that targets this need. Robert Love, former "Chief Architect, Linux Desktop" at Novell, kernel hacker of many years, and Gnome developer of well known features such as Beagle and NetworkManager, attempts in this book to document the Linux system call and C API to common systems programming tasks. Given that he developed the pre-emptive kernel and inotify he has the knowledge." Read below for the rest of Jon's review. Linux System Programming author Robert Love pages 388 publisher O'Reilly Media rating 8/10 reviewer Jon Mitchell ISBN 9780596009588 summary The Linux system call and C API explored in depth. Getting this book out of the box, I had wrongly been expecting a cookbook style that I would get instant gratification from. Although structured around common programming tasks, it doesn't lend itself to just dipping in. The section on time lists a handful of ways that "time" is available to the programmer; jump into the middle of the section and you might miss the most suitable one for the job in hand. The book rewards reading it in larger chunks.

This doesn't mean it is necessary to read it from cover to cover. Logically organized into chapters around "things you want to do", such as file access, memory management and process management it will lead you in with a survey of techniques you might be familiar with, before drilling down with advanced methods.

Knowing advanced methods for performance is great, but not at all costs. One of the most useful and practical lessons this book gives is to encourage you to think about error conditions that may occur during a system call. Early on, in the section on reading files, a detailed example is given on reading from a file. Every possible case of return code from the read call is described together with what it means and how you should handle it — it can be surprising that 7 possible outcomes are listed, with good descriptions of what to do with each of them.

This good practice by example continues throughout the book. Every system call described also lists the errors that may occur. This does show up a slight weakness: many system calls share a common set of errors which are repeated many times in the text. If you are not paying attention it may feel like you are just flipping through man pages. However you are soon halted by the easy introduction of an advanced concept to get your teeth into.

These are done in a nicely graded level for each topic. In "file access" to give an example, you are lead from simple read/write calls, through to what the C library can provide in buffering, to improved performance using mmap. The techniques continue with descriptions of I/O schedulers and how the kernel will order hardware disk access, scatter/gather, and ends up with how it is possible to order block reads/writes yourself bypassing any scheduler.

You are hardly aware of the progression, as the pacing is very well done. New concepts clearly fit into what you have seen so far — current sections signpost the practical use of what is being explained and at what cost, allowing clear consideration of the use of advanced features against any consequences.

For process management discussion starts with fork and exec, before moving onto user ids and groups, covers daemonification and goes onto process scheduling, including real time scheduling. Throughout the book each new call is illustrated with a short code snippet showing the call being used in a practical situation.

Not everything is present and correct. The author immediately states that networking is not covered at all. This is a shame as this subject would benefit from the depth of coverage given to the topics in this book — although no doubt would increase the number of pages considerably. Perhaps scope for a second volume. The length of some sections seems odd — Asynchronous file I/O is whizzed through in a page with no code example, whereas I/O schedulers gets a luxurious 12.

On the other hand there are some unexpected and useful extras, such as a discussion in the appendix of gcc C language extensions and how they might be used to fine tune your code.

The books stated target is for modern Linux development, a 2.6.22 kernel, gcc 4.2 and glibc 2.5. Many calls have been standardized by POSIX, and where this is so it are noted in the text, so a large portion of the content is useful on other systems. There is even the occasional mention of non-Linux system calls, the use of which is not encouraged, but shown so you know how they function if you come across them in older code.

I recommend this book to anyone who has a need to developing Linux applications. The book is not a primer in C on Unix, so you are expected to be familiar at least to the level of K&R. From this level though the journey into getting the best from the kernel and C library into your programs is easy going and enjoyable.

You can purchase Linux System Programming from amazon.com. Slashdot welcomes readers' book reviews -- to see your own review here, read the book review guidelines, then visit the submission page.

13 of 98 comments (clear)

  1. What I like about it. by bytesex · · Score: 4, Interesting

    I like UNIX systems programming when it's complete; even when that surprises me. Recently, for example, I had to find a way to know how many processes had open file descriptors to a certain file. You know, the old shared database thing; so that I can make sure that I'm the only one in at a certain point (inside a file lock), to do some checks an'all. To no avail; UNIX basically said: 'if you can't do it with file locks, don't bother'. Then I discovered the good old sys/ipc.h and the associated sys/sem.h and sys/shm.h. Turns out that my issue *has* been thought about, and in a good way too. Sure, the APIs aren't all 'modern' feeling; lots of things are done with extremely short function-names, ellipsis and setting bits inside special structs, but it works. And it's fast too.

    Now if they only had a good standard API to a versioned, networked filesystem. Then I would be in heaven. But a guy can dream...

    --
    Religion is what happens when nature strikes and groupthink goes wrong.
    1. Re:What I like about it. by morgan_greywolf · · Score: 3, Funny

      Now if they only had a good standard API to a versioned, networked filesystem. Then I would be in heaven. But a guy can dream...
      If you want VMS, you know where to find it. ;)
  2. Re:What about a C++ coder? by Chandon+Seldon · · Score: 4, Funny

    How hard would it be for a C++ coder to dig into this book?

    Should be pretty easy. All the code examples are valid C++. All you need to do is remember that "class" is called "struct" and that you have to mangle your own names.

    --
    -- The act of censorship is always worse than whatever is being censored. Always.
  3. K&R by christurkel · · Score: 4, Interesting

    You can probably tell I can't program, but what is "K&R level of experience" ?

    --

    CDE open sourced! https://sourceforge.net/projects/cdesktopenv/
  4. Re:All accessible from Perl! by moderatorrater · · Score: 3, Insightful

    Best of all, Perl is damn fast, usually on par with C for most tasks Any way you could back that up with some numbers? I don't mean to say that you're wrong, but I'm skeptical about any claim that says an interpreted language can beat a compiled one. I would even be surprised if compiled perl could beat compiled C since C's been worked on so much longer and compiling perl into a binary isn't really its focus anyway.
  5. Re:What about a C++ coder? by Peaker · · Score: 4, Informative

    How hard would it be for a C++ coder to dig into this book?

    Should be pretty easy. All the code examples are valid C++. All you need to do is remember that "class" is called "struct" and that you have to mangle your own names.

    C++ is not a superset of C, and is definitely not supposed to be written like C.

    For example variable-length arrays (added by C99) are not supported by C++ (which has vector objects instead).
  6. Thou shalt not ignore warnings by mi · · Score: 5, Informative

    Build your code with -Wall -Werror (or your compiler's equivalent). Once you clean up all the crud, that pops up, crank it up with -W -Wno-unused-parameter -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith. Once there — add -Wreturn-type -Wcast-qual -Wswitch -Wshadow -Wcast-align and tighten up by removing the no in -Wno-unused-parameter. The -Wwrite-strings is essential, if you wish your code to be compiled with a C++ compiler some day (hint: the correct type for static strings is " const char *").

    For truly clean code, add -Wchar-subscripts -Winline -Wnested-externs -Wredundant-decls.

    The people, who wrote and maintain the compiler, are, most likely, several levels above you in understanding programming in general and C-programming in particular. Ignoring the advice their code generates is foolish on your part...

    As a minimum, solved warnings will make your code more readable by reducing/eliminating the "Why is he doing this?" questions. More often than not, they point out bugs you would otherwise spend hours chasing with a debugger later.

    And they make your code more portable. But if you don't understand, why a warning is generated — ask around. Don't just "shut it up". For example, initializing a variable at declaration is usually a no-no. If the compiler thinks, the variable may be used before being initialized, scrutinize your program's flow. If you can't figure out, it may some times be better to disable this one warning temporarily with -Wno-uninitialized to move on, instead of shutting it up for ever by a bogus "= 0" or some such...

    The book may well say something about respecting warnings, but the review does not, which is a shame.

    --
    In Soviet Washington the swamp drains you.
    1. Re:Thou shalt not ignore warnings by david.emery · · Score: 4, Informative

      Many studies (e.g. the Bell Labs 5-ESS fault analysis) and anecdotal stories indicate that failing to check the error return on a system call (or any other function, for that matter) is all-too-common. Adding to this problem, when a system call fails, often the manifestation/error/seg fault is not at that point of call, but further down, when a pointer/variable you expect to have meaningful data is null/garbage...

      That's why, when we did the Ada Binding to POSIX (IEEE 1003.5/ ISO 9945), we decided to accept the overhead of imposing exceptions for system call error returns (in most cases). You can't ignore the exception!

      This raised two interesting concerns that we discussed when developing the standard:

      1. What about tasking/threads/concurrency? The requirement on the implementation was to set up per-task errno values. From an implementation perspective, this meant that you needed to go outside of the standard interface to correctly implement POSIX/Ada, as you needed to grab the errno value and load it into task-specific storage, or require that your underlying POSIX threads implementation (if that's how you built the Ada runtime) do that for you. In practice, this is not too onerous, and it's proven to be a real boon for ensuring proper behavior (including debugging) in a multithreaded/multitasking environment.

      2. We also needed to think about the situation (usually representing really poor programming) where an unhandled exception (from a system call, an application call, or a language predefined exception) rips up the callstack and terminates the process. We wanted a return value from the process exit that would be 'close to 1 but not collide with commonly used values.' The number we chose: 42 (with the appropriate citation in the bibliography:-)

      So sure, a C++ program can use the C binding, but I think defining and using C++ exceptions in a better C++ interface would be preferred.

      dave (Tech Editor for the original IEEE P1003.5 project...)

  7. Re:All accessible from Perl! by mr_mischief · · Score: 3, Informative

    Perl is compiled into an AST, goes through code improvements, and then is executed.

    Since it typically goes through this every time you use a program from the command line, the startup time tends to be pretty heavy.

    If you're using something like mod_perl or FastCGI or some other caching dispatch mechanism, your program gets dispatched without recompilation if it hasn't been changed.

    If your program is long-running, then the startup cost can become negligible.

    Perl's common routines are written in optimized C and with good algorithmic design in mind. If someone writes an equivalent from scratch in C instead of using a good library, then the Perl version will have been designed and refined by far more people.

    It's true that in many cases C comes out well faster than Perl, but those cases are not as common as people tend to think.

  8. Re:What about a C++ coder? by Chandon+Seldon · · Score: 4, Informative

    C++ is not a superset of C, and is definitely not supposed to be written like C.

    C++ is damn close to being a superset of C. Any C code examples given in this book are almost sure to be valid C++. Further, the fact that C code makes for awkward and ugly C++ code doesn't mean that it isn't *valid* C++ code.

    C and C++ are very different languages in programming style, but anyone who knows C++ already knows the C syntax and semantics - at most they'll need to learn the modern C programming style to actually use it.

    --
    -- The act of censorship is always worse than whatever is being censored. Always.
  9. Re:Ada's approach to syscall-failures by david.emery · · Score: 3, Informative

    That's not surprising, since the use of '42' is an artifact of the Ada binding, and those systems do not by default contain an implementation of 1003.5/9945. They should, but that's another story. Ada actually meshes very nicely with Unix, and is a good choice for system-level programming above the kernel level. Strong Typing -is your friend-! (I've been doing library level system programming on Unix systems, starting with Ultrix in 1984...)

    The standard Linux/Solaris Ada compiler is the GNU Ada Compiler, http://www.gnat.com

    But at least it's good to know there isn't a conflict.

          dave

  10. Re:What about a C++ coder? by Evil+Pete · · Score: 3, Informative

    C++ was originally a superset of C. But later changes to C / C++ have drifted considerably from that. However, that means that generally C shouldn't be a problem for C++ programmers. There are large differences in the philosophy though that will affect the quality of your C code.

    --
    Bitter and proud of it.
  11. Re:What about a C++ coder? by Evil+Pete · · Score: 3, Informative

    I didn't say 'recently'. I remember it was stated that C++ WAS a superset. Though it was probably moer accurate to say a superset of ANSI C. In fact there were early C++ compilers that actually preprocessed the C++ code into C first. Of course I am talking 15-20 years ago.

    So I stick to my remarks.

    Bloody young whippersnappers.

    A comment that follows has a link to Stroustrop's page about this. Yes it is not a mathematical superset. But it is practically one:

    Thus, C++ is as much a superset of ANSI C as ANSI C is a superset of K&R C and much as ISO C++ is a superset of C++ as it existed in 1985.

    Well written C tends to be legal C++ also. For example, every example in Kernighan & Ritchie: "The C Programming Language (2nd Edition)" is also a C++ program.


    --
    Bitter and proud of it.