Hands-On System Programming with Linux
eBook - ePub

Hands-On System Programming with Linux

Explore Linux system programming interfaces, theory, and practice

Kaiwan N Billimoria

Share book
  1. 794 pages
  2. English
  3. ePUB (mobile friendly)
  4. Available on iOS & Android
eBook - ePub

Hands-On System Programming with Linux

Explore Linux system programming interfaces, theory, and practice

Kaiwan N Billimoria

Book details
Book preview
Table of contents
Citations

About This Book

Get up and running with system programming concepts in Linux

Key Features

  • Acquire insight on Linux system architecture and its programming interfaces
  • Get to grips with core concepts such as process management, signalling and pthreads
  • Packed with industry best practices and dozens of code examples

Book Description

The Linux OS and its embedded and server applications are critical components of today's software infrastructure in a decentralized, networked universe. The industry's demand for proficient Linux developers is only rising with time. Hands-On System Programming with Linux gives you a solid theoretical base and practical industry-relevant descriptions, and covers the Linux system programming domain. It delves into the art and science of Linux application programming— system architecture, process memory and management, signaling, timers, pthreads, and file IO.

This book goes beyond the use API X to do Y approach; it explains the concepts and theories required to understand programming interfaces and design decisions, the tradeoffs made by experienced developers when using them, and the rationale behind them. Troubleshooting tips and techniques are included in the concluding chapter.

By the end of this book, you will have gained essential conceptual design knowledge and hands-on experience working with Linux system programming interfaces.

What you will learn

  • Explore the theoretical underpinnings of Linux system architecture
  • Understand why modern OSes use virtual memory and dynamic memory APIs
  • Get to grips with dynamic memory issues and effectively debug them
  • Learn key concepts and powerful system APIs related to process management
  • Effectively perform file IO and use signaling and timers
  • Deeply understand multithreading concepts, pthreads APIs, synchronization and scheduling

Who this book is for

Hands-On System Programming with Linux is for Linux system engineers, programmers, or anyone who wants to go beyond using an API set to understanding the theoretical underpinnings and concepts behind powerful Linux system programming APIs. To get the most out of this book, you should be familiar with Linux at the user-level logging in, using shell via the command line interface, the ability to use tools such as find, grep, and sort. Working knowledge of the C programming language is required. No prior experience with Linux systems programming is assumed.

Frequently asked questions

How do I cancel my subscription?
Simply head over to the account section in settings and click on “Cancel Subscription” - it’s as simple as that. After you cancel, your membership will stay active for the remainder of the time you’ve paid for. Learn more here.
Can/how do I download books?
At the moment all of our mobile-responsive ePub books are available to download via the app. Most of our PDFs are also available to download and we're working on making the final remaining ones downloadable now. Learn more here.
What is the difference between the pricing plans?
Both plans give you full access to the library and all of Perlego’s features. The only differences are the price and subscription period: With the annual plan you’ll save around 30% compared to 12 months on the monthly plan.
What is Perlego?
We are an online textbook subscription service, where you can get access to an entire online library for less than the price of a single book per month. With over 1 million books across 1000+ topics, we’ve got you covered! Learn more here.
Do you support text-to-speech?
Look out for the read-aloud symbol on your next book to see if you can listen to it. The read-aloud tool reads text aloud for you, highlighting the text as it is being read. You can pause it, speed it up and slow it down. Learn more here.
Is Hands-On System Programming with Linux an online PDF/ePUB?
Yes, you can access Hands-On System Programming with Linux by Kaiwan N Billimoria in PDF and/or ePUB format, as well as other popular books in Informatica & Sistemi operativi. We have over one million books available in our catalogue for you to explore.

Information

Year
2018
ISBN
9781788996747
Edition
1

Signaling - Part I

Signals are a crucial mechanism for the Linux system developer to understand and exploit. We cover this rather large topic over two chapters in this book, this chapter and the next one.
In this chapter, the reader is introduced to what signals are, why they are useful to the systems developer, and, most importantly of course, how exactly the developer is to handle and thus exploit the signalling mechanism.
We will continue this exploration in the next chapter.
In this chapter, the reader will learn the following:
  • What exactly signals are.
  • Why they are useful.
  • The available signals.
  • How exactly you can handle signals in an application, which really involves many things—blocking or unblocking signals, writing safe handlers, getting rid of pesky zombies once and for all, working with apps where the signal volume is high, and more.

Why signals?

At times, the systems programmer requires the OS to provide an asynchronous facility—some way of letting you know that a certain event or condition has occurred. Signals provide that very feature on the Unix/Linux OSes. A process can trap or subscribe to a signal; when this occurs, the process will asynchronously be notified of the fact by the OS, and will then run the code of a function in response: a signal handler.
Take the following example cases:
  • A CPU-intensive process is busy working on a scientific or mathematical calculation (for easy understanding, let's say it's generating primes); recall (from Chapter 3, Resource Limits) that there is an upper limit on CPU usage and that it's been set to a particular value. What if it's breached? The process will be killed by default. Can we prevent this?
  • The developer wants to perform a common task: set up a timer and have it expire in, say, 1.5 seconds from now. How will the OS inform the process that the timer has expired?
  • On some Sys V Unixes (typically running on enterprise-class servers), what if a sudden power failure occurs? An event is broadcast to all processes (that have expressed an interest in, or subscribed to the event) informing them of the same: they could flush their buffers, and save their data.
  • A process has an inadvertent defect (a bug); it makes an invalid memory access. The memory subsystem (well, technically, the MMU and the OS) determines it must be killed. How exactly will it be killed?
  • Linux's asynchronous IO (AIO) framework, and many other such scenarios.
All of these example scenarios are serviced by the same mechanism: signals.

The signal mechanism in brief

A signal can be defined as an asynchronous event that is delivered to a target process. Signals are delivered to the target process either by another process or the OS (the kernel) itself.
At the code level, a signal is merely an integer value; more correctly, it is a bit in a bitmask. It's important to understand that, although the signal may seem like an interrupt, it is not an interrupt. An interrupt is a hardware feature; a signal is purely a software mechanism.
OK, let's try a simple exercise: run a process, putting it in an infinite loop, and then manually send it a signal via the keyboard. Find the code in (ch11/sig1.c):
int main(void)
{
unsigned long int i=1;
while(1) {
printf("Looping, iteration #%02ld ...\n", i++);
(void)sleep(1);
}
exit (EXIT_SUCCESS);
}
Why is the sleep(1); code typecast to (void)? This is our way of informing the compiler (and possibly any static analysis tool) that we are not concerned about its return value. Well, the fact is we should be; there will be more on this later.
It's working is quite obvious: let's build and run it, and, after the third loop iteration, we press the Ctrl + C key combination on the keyboard.
$ ./sig1 
Looping, iteration #01 ...
Looping, iteration #02 ...
Looping, iteration #03 ...
^C
$
Yes, as expected, the process terminates. But how exactly did this happen?
Here is the answer in brief: signalling. More verbosely, this is what occurs (it's still kept simple, though): when the user presses the Ctrl + C key combination (shown as ^C in the output), the kernel's tty layer code processes this input, cooks the input key combination into, and delivers a signal to the foreground process on the shell.
But, hang on a second. Remember, a signal is just an integer value. So, which integer? Which signal? The Ctrl + C key combination is mapped to the the SIGINT signal, integer value 2, thus causing it to be delivered to the process. (The next section begins to explain the different signals; for now, let's not get too stressed out about it).
So, OK, the SIGINT signal, value 2, was delivered to our sig1 process. But then what? Here, again, is a key point: every signal is associated with a function to run when it is delivered; this function is called the signal handler. If we do not change it, the default signal function runs. Well, that brings up the question: Since we have not written any default (or other) signal-handling code, then who has provided this default signal handler function? The short answer is this: the OS (the kernel) handles all cases in which a process receives a signal for which the app has not installed any handler; in other words, for the default case.
The action performed by the signal handler function or the underlying kernel code determines what will happen to the target process when the signal arrives. So, now we can understand better: the action carried out by the default signal handler (kernel code, really) for the SIGINT signal is to terminate the process, in effect, causing the receiving process to die.
We show this in the form of a diagram as follows:
Signal delivered via keyboard, default handler causes process to die
From this diagram, we can see the following steps:
  1. A process, P comes alive and runs its code.
  2. The user presses ^C, in effect causing the SIGINT signal to be sent to the process.
  1. As we have not set up any signal handler, the default signal handling action for this signal, which is part of the OS, is invoked.
  2. This default signal handling code within the OS causes the process to die.
FYI, for the default case—that is, all cases where the application developer has not installed a specific signal-handling routine (we will learn how exactly to install our own signal handlers shortly)—what exactly does the OS code that handles these cases do? Depending on the signal being processed, the OS will perform one of these five possible actions (see the following table for details):
  • Ignore the signal
  • Stop the process
  • Continue the (previously stopped) process
  • Terminate the process
  • Terminate the process and emit a core dump
The really interesting and powerful thing is this: the programmer has the ability to change–to re-vector the signal handling to their own function(s)! In effect, we can ...

Table of contents