Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds
C++ System Programming Cookbook
C++ System Programming Cookbook

C++ System Programming Cookbook: Practical recipes for Linux system-level programming using the latest C++ features

eBook
€20.99 €23.99
Paperback
€29.99
Subscription
Free Trial
Renews at €18.99p/m

What do you get with eBook?

Product feature icon Instant access to your Digital eBook purchase
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
Product feature icon AI Assistant (beta) to help accelerate your learning
OR
Modal Close icon
Payment Processing...
tick Completed

Billing Address

Table of content icon View table of contents Preview book icon Preview Book

C++ System Programming Cookbook

Revisiting C++

This chapter acts as a refresher on C++ 11-20, which will be used throughout this book. We'll explain why C++ represents a great opportunity that shouldn't be missed when it comes to writing good quality code that's concise and more portable than ever.

This chapter does not contain all the new features introduced by C++ (11 through 20) – just the ones we will be using for the rest of this book. Specifically, you'll get a refresher (if you already know) or learn (if you are new) about the most essential new C++ skills needed to write modern code. You'll work, hands-on, with lambda expressions, atomics, and move semantics, just to mention a few.

This chapter will cover the following recipes:

  • Understanding C++ primitive types
  • Lambda expressions
  • Automatic type deduction and decltype
  • Learning how atomic works
  • Learning how nullptr works
  • Smart pointers unique_ptr and shared_ptr
  • Learning how semantics works
  • Understanding concurrency
  • Understanding the filesystem
  • The C++ Core Guidelines
  • Adding GSL to your makefile
  • Understanding concepts
  • Using span
  • Learning how Ranges work
  • Learning how modules work

Technical requirements

To let you try out the programs in this chapter immediately, we've set up a Docker image that has all the tools and libraries we'll need throughout this book. It's based on Ubuntu 19.04.

In order to set it up, follow these steps:

  1. Download and install the Docker Engine from www.docker.com.
  2. Pull the image from Docker Hub: docker pull kasperondocker/system_programming_cookbook:latest.
  3. The image should now be available. Type in the following command to view the image: docker images.
  4. Now, you should have the following image: kasperondocker/system_programming_cookbook.
  5. Run the Docker image with an interactive shell with the help of the following command: docker run -it --cap-add sys_ptrace kasperondocker/system_programming_cookbook:latest /bin/bash.
  6. The shell on the running container is now available. Use root@39a5a8934370/# cd /BOOK/ to get all the programs that have been developed for the chapters in this book.

The --cap-add sys_ptrace argument is needed to allow GDB to set breakpoints in the Docker container which, by default, Docker does not allow.

Disclaimer: The C++20 standard has been approved (that is, technically finalized) by WG21 in a meeting in Prague at the end of February. This means that the GCC compiler version that this book uses, 8.3.0, does not include (or has very, very limited support for) the new and cool C++20 features. For this reason, the Docker image does not include the C++20 recipe code. GCC keeps the development of the newest features in branches (you have to use appropriate flags for that, for example, -std=c++2a); therefore, you are encouraged to experiment with them by yourself. So, clone and explore the GCC contracts and module branches and have fun.

Understanding C++ primitive types

This recipe will show all the primitive data types defined by the C++ standard, as well as their size.

How to do it...

In this section, we'll have a closer look at what primitives the C++ standard defines and what other information is important. We'll also learn that although the standard does not define a size for each, it defines another important parameter:

  1. First, open a new Terminal and type in the following program:
#include <iostream>
#include <limits>

int main ()
{
// integral types section
std::cout << "char " << int(std::numeric_limits<char>::min())
<< "-" << int(std::numeric_limits<char>::max())
<< " size (Byte) =" << sizeof (char) << std::endl;
std::cout << "wchar_t " << std::numeric_limits<wchar_t>::min()
<< "-" << std::numeric_limits<wchar_t>::max()
<< " size (Byte) ="
<< sizeof (wchar_t) << std::endl;
std::cout << "int " << std::numeric_limits<int>::min() << "-"
<< std::numeric_limits<int>::max() << " size
(Byte) ="
<< sizeof (int) << std::endl;
std::cout << "bool " << std::numeric_limits<bool>::min() << "-"
<< std::numeric_limits<bool>::max() << "
size (Byte) ="
<< sizeof (bool) << std::endl;

// floating point types
std::cout << "float " << std::numeric_limits<float>::min() <<
"-"
<< std::numeric_limits<float>::max() << " size
(Byte) ="
<< sizeof (float) << std::endl;
std::cout << "double " << std::numeric_limits<double>::min()
<< "-"
<< std::numeric_limits<double>::max() << " size
(Byte) ="
<< sizeof (double) << std::endl;
return 0;
}
  1. Next, build (compile and link) g++ primitives.cpp.
  2. This will produce an executable file with the (default) name of a.out.

How it works...

The output of the preceding program will be something like this:

This represents the minimum and maximum values that a type can represent and the size in bytes for the current platform.

The C++ standard does not define the size of each type, but it does define the minimum width:

  • char: Minimum width = 8
  • short int: Minimum width = 16
  • int: Minimum width = 16
  • long int: Minimum width = 32
  • long int int: Minimum width = 64

This point has huge implications as different platforms can have different sizes and a programmer should cope with this. To help us get some guidance regarding data types, there is the concept of a data model. A data model is a set of choices (a specific size for each type) made by each implementation (the psABI of the architecture that compilers and operating systems adhere to) to define all the primitive data types. The following table shows a subset of various types and data models that exist:

Data type LP32 ILP32 LLP64 LP64
char 8 8 8 8
short int 16 16 16 16
int 16 32 32 32
long 32 32 32 64
pointer 32 32 64 64

The Linux kernel uses the LP64 data model for 64-bit architectures (x86_64).

We briefly touched on the psABI topic (short for platform-specific Application Binary Interfaces (ABIs)). Each architecture (for example, x86_64) has a psABI specification that the OS adheres to. The GNU Compiler Collection (GCC) has to know these details as it has to know the sizes of the primitive types it compiles. The i386.h GCC header file contains the size of the primitive data types for that architecture:

root@453eb8a8d60a:~# uname -a
Linux 453eb8a8d60a 4.9.125-linuxkit #1 SMP Fri Sep 7 08:20:28 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

The program output shows that the current OS (actually, the Ubuntu image we're running) uses the LP64 data model as expected and that the machine's architecture is x86_64.

There's more...

As we've seen, the C++ standard defines the following primitive data types:

  • Integer: int
  • Character: char
  • Boolean: bool
  • Floating point: float
  • Double floating point: double
  • Void: void
  • Wide character: wchar_t
  • Null pointer: nullptr_­t

Data types can have other information so that their types can be defined:

  • Modifiers: signed, unsigned, long, and short
  • Qualifiers: const and restrict
  • Storage type: auto, static, extern, and mutable

Obviously, not all these additional attributes can be applied to all the types; for example, unsigned cannot be applied to the float and double types (their respective IEEE standards would not allow that).

See also

Lambda expressions

A lambda expression (or lambda function) is a convenient way of defining an anonymous, small, and one-time use function to be used in the place right where it is needed. Lambda is particularly useful with Standard Template Library (STL), as we'll see.

How to do it...

In this section, we'll write some code in order to get familiar with lambda expressions. Although the mechanics are important, pay attention to the code readability with lambda, especially in conjunction with STL. Follow these steps:

  1. In this program, the lambda function gets an integer and prints it to standard output. Let's open a file named lambda_01.cpp and write the following code in it:
#include <iostream>
#include <vector>
#include <algorithm>
int main ()
{
std::vector<int> v {1, 2, 3, 4, 5, 6};
for_each (begin(v), end(v), [](int x) {std::cout << x
<< std::endl;});
return 0;
}
  1. In this second program, the lambda function captures a prefix by reference and prepends it to the integer in the standard output. Let's write the following code in a file called lambda_02.cpp:
#include <iostream>
#include <vector>
#include <algorithm>
int main ()
{
std::vector<int> v {1, 2, 3, 4, 5, 6};
std::string prefix ("0");
for_each (begin(v), end(v), [&prefix](int x) {std::cout
<< prefix << x << std::endl;});
return 0;
}
  1. Finally, we compile it with g++ lambda_02.cpp.

How it works...

In the first example, the lambda function just gets an integer as input and prints it. Note that the code is concise and readable. Lambda can capture the variables in scope by reference, &, or by value, =.

The output of the second program is as follows:

In the second example, the lambda captures the variable prefix by reference, making it visible to the lambda. Here, we captured the prefix variable by reference, but we might have captured any of the following:

  • All the variables by reference [&]
  • All the variables by value [=]
  • Specifying what variables to capture and how to capture them [&var1, =var2]

There are cases where we have to be explicit about the type to return, as in this case:

[](int x) -> std::vector<int>{
if (x%2)
return {1, 2};
else
return {3, 4};
});

The -> std::vector<int> operator, called trailing return type, tells the compiler that this lambda will return a vector of integers.

There's more...

Lambda can be decomposed into six parts:

  1. Capture clause: []
  2. Parameter list: ()
  3. Mutable specification: mutable
  4. Exception specification: noexcept
  5. Trailing return type: -> type
  6. Body: {}

Here, 1, 2, and 6 are mandatory.

Although optional, mutable specification and exception specification are worth having a look at as they might be handy in some circumstances. The mutable specification allows a by-value parameter to be modified by the body of the lambda. A variable in the parameter list is typically captured const-by-value, so the mutable specification just removes this restriction. The second case is the exception specification, which we can use to specify the exceptions the lambda might throw.

See also

The books Effective Modern C++ by Scott Meyers and The C++ Programming Language by Bjarne Stroustrup cover these topics in great detail.

Automatic type deduction and decltype

C++ offers two mechanisms for deducting types from an expression: auto and decltype(). auto is used to deduce a type from its initializer, while decltype() is used to deduce a type for more complex cases. This recipe will show examples of how to use both.

How to do it...

It might be handy (and it actually is) to avoid explicitly specifying the type of variable that will be used, especially when it is particularly long and used very locally:

  1. Let's start with a typical example:
std::map<int, std::string> payslips;
// ...
for (std::map<int,
std::string>::const_iterator iter = payslips.begin();
iter !=payslips.end(); ++iter)
{
// ...
}
  1. Now, let's rewrite it with auto:
std::map<int, std::string> payslips;
// ...
for (auto iter = payslips.begin(); iter !=payslips.end(); ++iter)
{
// ...
}
  1. Let's look at another example:
auto speed = 123;         // speed is an int
auto height = calculate (); // height will be of the
// type returned by calculate()

decltype() is another mechanism offered by C++ that can deduce the type of expression when the expression is more complex than the auto case.

  1. Let's look at this using an example:
decltype(a) y = x + 1;  // deducing the type of a
decltype(str->x) y; // deducing the type of str->x, where str is
// a struct and x
// an int element of that struct

Could we use auto instead of decltype() in these two examples? We'll take a look in the next section.

How it works...

The first example with auto shows that the type is deduced, at compile time, from the right-hand parameter. auto is used in simple cases.

decltype() deduces the type of expression. In the example, it defines the y variable so that it's the same type as a. As you can imagine, this would not be possible with auto. Why? This is pretty simple: decltype() tells the compiler to define a variable of a specific type; in the first example, y is a variable with the same type as a. With auto, the type is deduced automatically.

We should use auto and decltype() anytime we don't have to explicitly specify the type of a variable; for example, when we need a double type (and not a float). It's worth mentioning that both auto and decltype() deduct types of expressions that are already known to the compiler, so they are not runtime mechanisms.

There's more...

There is a specific case that must be mentioned. When auto uses {} (uniform initializers) for type deduction, it can cause some headaches (or at least behaviors that we wouldn't expect). Let's look at an example:

auto fuelLevel {0, 1, 2, 3, 4, 5};

In this case, the type that's being deduced is initializer_list<T> and not an array of integers, as we could expect.

See also

The books Effective Modern C++ by Scott Meyers and The C++ Programming Language by Bjarne Stroustrup cover these topics in great detail.

Learning how atomic works

Traditionally, C and C++ have a long tradition of portable code for system programming. The atomic feature that was introduced in the C++11 standard reinforces this by adding, natively, the guarantee that an operation is seen as atomic by other threads. Atomic is a template, such as template <class T> struct atomic; or template <class T> struct atomic<T*>;. C++20 has added shared_ptr and weak_ptr to T and T*. Any operation that's performed on the atomic variable is now protected from other threads.

How to do it...

std::atomic is an important aspect of modern C++ for dealing with concurrency. Let's write some code to master the concept:

  1. The first snippet of code shows the basics of atomic operations. Let's write this now:
std::atomic<int> speed (0);         // Other threads have access to the speed variable
auto currentSpeed = speed.load(); // default memory order: memory_order_seq_cst
  1. In this second program, we can see that the is_lock_free() method returns true if the implementation is lock-free or if it has been implemented using a lock. Let's write this code:
#include <iostream>
#include <utility>
#include <atomic>
struct MyArray { int z[50]; };
struct MyStr { int a, b; };
int main()
{
std::atomic<MyArray> myArray;
std::atomic<MyStr> myStr;
std::cout << std::boolalpha
<< "std::atomic<myArray> is lock free? "
<< std::atomic_is_lock_free(&myArray) << std::endl
<< "std::atomic<myStr> is lock free? "
<< std::atomic_is_lock_free(&myStr) << std::endl;
}
  1. Let's compile the program. When doing so, you may need to add the atomic library to g++ (due to a GCC bug) with g++ atomic.cpp -latomic.

How it works...

std::atomic<int> speed (0); defines a speed variable as an atomic integer. Although the variable will be atomic, this initialization is not atomic! Instead, the following code: speed +=10; atomically increases the speed of 10. This means that there will not be race conditions. By definition, a race condition happens when among the threads accessing a variable, at least 1 is a writer.

The std::cout << "current speed is: " << speed; instruction reads the current value of the speed automatically. Pay attention to the fact that reading the value from speed is atomic but what happens next is not atomic (that is, printing it through cout). The rule is that read and write are atomic but the surrounding operations are not, as we've seen.

The output of the second program is as follows:

The basic operations for atomic are load, store, swap, and cas (short for compare and swap), which are available on all types of atomics. Others are available, depending on the types (for example, fetch_add).

One question remains open, though. How come myArray uses locks and myStr is lock-free? The reason is simple: C++ provides a lock-free implementation for all the primitive types, and the variables inside MyStr are primitive types. A user will set myStr.a and myStr.b. MyArray, on the other hand, is not a fundamental type, so the underlying implementation will use locks.

The standard guarantee is that for each atomic operation, every thread will make progress. One important aspect to keep in mind is that the compiler makes code optimizations quite often. The use of atomics imposes restrictions on the compiler regarding how the code can be reordered. An example of a restriction is that no code that preceded the write of an atomic variable can be moved after the atomic write.

There's more...

In this recipe, we've used the default memory model called memory_order_seq_cst. Some other memory models that are available are:

  • memory_order_relaxed: Only the current operation atomicity is guaranteed. That is, there are no guarantees on how memory accesses in different threads are ordered with respect to the atomic operation.
  • memory_order_consume: The operation is ordered to happen once all accesses to memory in the releasing thread that carry a dependency on the releasing operation have happened.
  • memory_order_acquire: The operation is ordered to happen once all accesses to memory in the releasing thread have happened.
  • memory_order_release: The operation is ordered to happen before a consume or acquire operation.
  • memory_order_seq_cst: The operation is sequentially consistent ordered.

See also

The books Effective Modern C++ by Scott Meyers and The C++ Programming Language by Bjarne Stroustrup cover these topics in great detail. Furthermore, the Atomic Weapons talk from Herb Sutter, freely available on YouTube (https://www.youtube.com/watch?v=A8eCGOqgvH4), is a great introduction.

Learning how nullptr works

Before C++11, the NULL identifier was meant to be used for pointers. In this recipe, we'll see why this was a problem and how C++11 solved it.

How to do it...

To understand why nullptr is important, let's look at the problem with NULL:

  1. Let's write the following code:
bool speedUp (int speed);
bool speedUp (char* speed);
int main()
{
bool ok = speedUp (NULL);
}
  1. Now, let's rewrite the preceding code using nullptr:
bool speedUp (int speed);
bool speedUp (char* speed);
int main()
{
bool ok = speedUp (nullptr);
}

How it works...

The first program might not compile or (if it does) call the wrong method. We would expect it to call bool speedUp (char* speed); instead. The problem with NULL was exactly this: NULL was defined as 0, which is an integer type, and used by the pre-processor (which was replacing all the occurrences of NULL with 0). This is a huge difference as nullptr is now among the C++ primitives types and managed by the compiler.

For the second program, the speedUp (overloaded) method is called with the char* pointer to nullptr. There is no ambiguity here – we're calling the version with the char* type.

There's more...

nullptr represents a pointer that does not point to any object:

int* p = nullptr;

Due to this, there is no ambiguity, which means that readability improves. Another example that improves readability is as follows:

if (x == nullptr) 
{
// ...\
}

This makes the code more readable and clearly indicates that we're comparing a pointer.

See also

The books Effective Modern C++ by Scott Meyers and The C++ Programming Language by Bjarne Stroustrup cover these topics in great detail.

Smart pointers – unique_ptr and shared_ptr

This recipe will show the basic usage of unique_ptr and shared_ptr. These smart pointers are the main helpers for programmers who don't want to deal with memory deallocation manually. Once you've learned how to use them properly, this will save headaches and nights of debugging sessions.

How to do it...

In this section, we'll look at the basic use of two smart pointers, std::unique_ptr and std::shared_ptr:

  1. Let's develop a unique_ptr example by developing the following class:
#include <iostream>
#include <memory>
class CruiseControl
{
public:
CruiseControl()
{
std::cout << "CruiseControl object created" << std::endl;
};
~CruiseControl()
{
std::cout << "CruiseControl object destroyed" << std::endl;
}
void increaseSpeedTo(int speed)
{
std::cout << "Speed at " << speed << std::endl;
};
};
  1. Now, let's develop a main class by calling the preceding class:
int main ()
{
std::cout << "unique_ptr test started" << std::endl;
std::unique_ptr<CruiseControl> cruiseControl =
std::make_unique<CruiseControl>();
cruiseControl->increaseSpeedTo(12);
std::cout << "unique_ptr test finished" << std::endl;
}
  1. Let's compile g++ unique_ptr_01.cpp.
  2. Another example with unique_ptr shows its behavior with arrays. Let's reuse the same class (CruiseControl):
int main ()
{
std::cout << "unique_ptr test started" << std::endl;
std::unique_ptr<CruiseControl[]> cruiseControl =
std::make_unique<CruiseControl[]>(3);
cruiseControl[1].increaseSpeedTo(12);
std::cout << "unique_ptr test finished" << std::endl;
}
  1. Let's see std::shared_ptr in action with a small program:
#include <iostream>
#include <memory>
class CruiseControl
{
public:
CruiseControl()
{
std::cout << "CruiseControl object created" << std::endl;
};
~CruiseControl()
{
std::cout << "CruiseControl object destroyed" << std::endl;
}
void increaseSpeedTo(int speed)
{
std::cout << "Speed at " << speed << std::endl;
};
};

main looks like this:

int main ()
{
std::cout << "shared_ptr test started" << std::endl;
std::shared_ptr<CruiseControl> cruiseControlMaster(nullptr);
{
std::shared_ptr<CruiseControl> cruiseControlSlave =
std::make_shared<CruiseControl>();
cruiseControlMaster = cruiseControlSlave;
}
std::cout << "shared_ptr test finished" << std::endl;
}

The How it works... section will describe these three programs in detail.

How it works...

By running the first unique_ptr program, that is, ./a.out, we get the following output:

unique_ptr is a smart pointer that embodies the concept of unique ownership. Unique ownership, simply put, means that there is one and only one variable that can own a pointer. The first consequence of this concept is that the copy operator is not allowed on two unique pointer variables. Just move is allowed, where the ownership is transferred from one variable to another. The executable that was run shows that the object is deallocated at the end of the current scope (in this case, the main function): CruiseControl object destroyed. The fact that the developer doesn't need to bother remembering to call delete when needed, but still keep control over memory, is one of the main advantages of C++ over garbage collector-based languages.

In the second unique_ptr example, with arrays, there are three objects of the CruiseControl type that have been allocated and then released. For this, the output is as follows:

    The third example shows usage of shared_ptr. The output of the program is as follows:

    The shared_ptr smart pointer represents the concept that an object is being pointed at (that is, by the owner) by more than one variable. In this case, we're talking about shared ownership. It is clear that the rules are different from the unique_ptr case. An object cannot be released until at least one variable is using it. In this example, we defined a cruiseControlMaster variable pointing to nullptr. Then, we defined a block and in that block, we defined another variable: cruiseControlSlave. So far, so good! Then, still inside the block, we assigned the cruiseControlSlave pointer to cruiseControlMaster. At this point, the object allocated has two pointers: cruiseControlMaster and cruiseControlSlave. When this block is closed, the cruiseControlSlave destructor is called but the object is not freed as it is still used by another one: cruiseControlMaster! When the program finishes, we see the shared_ptr test finished log and immediately after the cruiseControlMaster, as it is the only one pointing to the CruiseControl object release, the object and then the constructor is called, as reported in the CruiseControl object destroyed log.

    Clearly, the shared_ptr data type has a concept of reference counting to keep track of the number of pointers. These references are increased during the constructors (not always; the move constructor isn't) and the copy assignment operator and decreased in the destructors.

    Can the reference counting variable be safely increased and decreased? The pointers to the same object might be in different threads, so manipulating this variable might be an issue. This is not an issue as the reference counting variable is atomically managed (that is, it is an atomic variable).

    One last point about the size. unique_ptr is as big as a raw pointer, whereas shared_ptr is typically double the size of unique_ptr because of the reference counting variable.

    There's more...

    See also

    The books Effective Modern C++ by Scott Meyers and The C++ Programming Language by Bjarne Stroustrup cover these topics in great detail.

    Left arrow icon Right arrow icon
    Download code icon Download Code

    Key benefits

    • Learn to apply the latest C++ features (from C++11, 14, 17, and 20) to facilitate systems programming
    • Create robust and concurrent systems that make the most of the available hardware resources
    • Delve into C++ inbuilt libraries and frameworks to design robust systems as per your business needs

    Description

    C++ is the preferred language for system programming due to its efficient low-level computation, data abstraction, and object-oriented features. System programming is about designing and writing computer programs that interact closely with the underlying operating system and allow computer hardware to interface with the programmer and the user. The C++ System Programming Cookbook will serve as a reference for developers who want to have ready-to-use solutions for the essential aspects of system programming using the latest C++ standards wherever possible. This C++ book starts out by giving you an overview of system programming and refreshing your C++ knowledge. Moving ahead, you will learn how to deal with threads and processes, before going on to discover recipes for how to manage memory. The concluding chapters will then help you understand how processes communicate and how to interact with the console (console I/O). Finally, you will learn how to deal with time interfaces, signals, and CPU scheduling. By the end of the book, you will become adept at developing robust systems applications using C++.

    Who is this book for?

    This book is for C++ developers who want to gain practical knowledge of systems programming. Though no experience of Linux system programming is assumed, intermediate knowledge of C++ is necessary.

    What you will learn

    • Get up to speed with the fundamentals including makefile, man pages, compilation, and linking and debugging
    • Understand how to deal with time interfaces, signals, and CPU scheduling
    • Develop your knowledge of memory management
    • Use processes and threads for advanced synchronizations (mutexes and condition variables)
    • Understand interprocess communications (IPC): pipes, FIFOs, message queues, shared memory, and TCP and UDP
    • Discover how to interact with the console (console I/O)

    Product Details

    Country selected
    Publication date, Length, Edition, Language, ISBN-13
    Last updated date : Jun 04, 2025
    Publication date : Feb 21, 2020
    Length: 292 pages
    Edition : 1st
    Language : English
    ISBN-13 : 9781838648756
    Category :
    Languages :

    What do you get with eBook?

    Product feature icon Instant access to your Digital eBook purchase
    Product feature icon Download this book in EPUB and PDF formats
    Product feature icon Access this title in our online reader with advanced features
    Product feature icon DRM FREE - Read whenever, wherever and however you want
    Product feature icon AI Assistant (beta) to help accelerate your learning
    OR
    Modal Close icon
    Payment Processing...
    tick Completed

    Billing Address

    Product Details

    Last updated date : Jun 04, 2025
    Publication date : Feb 21, 2020
    Length: 292 pages
    Edition : 1st
    Language : English
    ISBN-13 : 9781838648756
    Category :
    Languages :

    Packt Subscriptions

    See our plans and pricing
    Modal Close icon
    €18.99 billed monthly
    Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
    Feature tick icon Constantly refreshed with 50+ new titles a month
    Feature tick icon Exclusive Early access to books as they're written
    Feature tick icon Solve problems while you work with advanced search and reference features
    Feature tick icon Offline reading on the mobile app
    Feature tick icon Simple pricing, no contract
    €189.99 billed annually
    Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
    Feature tick icon Constantly refreshed with 50+ new titles a month
    Feature tick icon Exclusive Early access to books as they're written
    Feature tick icon Solve problems while you work with advanced search and reference features
    Feature tick icon Offline reading on the mobile app
    Feature tick icon Choose a DRM-free eBook or Video every month to keep
    Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just €5 each
    Feature tick icon Exclusive print discounts
    €264.99 billed in 18 months
    Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
    Feature tick icon Constantly refreshed with 50+ new titles a month
    Feature tick icon Exclusive Early access to books as they're written
    Feature tick icon Solve problems while you work with advanced search and reference features
    Feature tick icon Offline reading on the mobile app
    Feature tick icon Choose a DRM-free eBook or Video every month to keep
    Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just €5 each
    Feature tick icon Exclusive print discounts

    Frequently bought together


    Stars icon
    Total 134.97
    C++ System Programming Cookbook
    €29.99
    Expert C++
    €32.99
    Modern C++ Programming Cookbook
    €71.99
    Total 134.97 Stars icon

    Table of Contents

    12 Chapters
    Getting Started with System Programming Chevron down icon Chevron up icon
    Revisiting C++ Chevron down icon Chevron up icon
    Dealing with Processes and Threads Chevron down icon Chevron up icon
    Deep Dive into Memory Management Chevron down icon Chevron up icon
    Using Mutexes, Semaphores, and Condition Variables Chevron down icon Chevron up icon
    Pipes, First-In First-Out (FIFO), Message Queues, and Shared Memory Chevron down icon Chevron up icon
    Network Programming Chevron down icon Chevron up icon
    Dealing with Console I/O and Files Chevron down icon Chevron up icon
    Dealing with Time Interfaces Chevron down icon Chevron up icon
    Managing Signals Chevron down icon Chevron up icon
    Scheduling Chevron down icon Chevron up icon
    Other Books You May Enjoy Chevron down icon Chevron up icon

    Customer reviews

    Rating distribution
    Full star icon Full star icon Full star icon Half star icon Empty star icon 3.8
    (4 Ratings)
    5 star 50%
    4 star 25%
    3 star 0%
    2 star 0%
    1 star 25%
    Scott Hutchinson Mar 16, 2020
    Full star icon Full star icon Full star icon Full star icon Full star icon 5
    I had the privilege to be a technical reviewer on this book. The C++ System Programming Cookbook provides a detailed, hands-on introduction to many critical system programming tasks on the Linux operating system. This book is particularly helpful for those C++ programmers who are not very familiar with Linux. In addition, all the code samples for the book are available in a Docker image with Ubuntu 19.04 and g++ 8.3.0 installed, which provides a side benefit for the reader to learn how to develop and debug C++ in a Docker container. While some of the tasks are demonstrated using POSIX APIs in C/C++, most of the examples are written in modern C++, taking advantage of some features of C++11, such as the std::chrono namespace and the std::unique_lock, std::promise, and std::future classes. Even some C++17 features are included, such as the std::filesystem namespace. Whether you are familiar with Linux or not, reading this concise book and running all the code samples will teach you the fundamental techniques you need to develop robust systems applications using C++.
    Amazon Verified review Amazon
    Jim Ledin May 14, 2022
    Full star icon Full star icon Full star icon Full star icon Full star icon 5
    I really like how the book starts with an explanation of the essential features of the Linux architecture and makes no assumption of prior Linux experience. This provides a strong foundation for later chapters that delve into the details of programming Linux at the system level.I also like the thorough introduction to C++ 11 through 20. This is a great help to those of us with experience in C++ from years past, but who haven't kept up with the recent (and exciting!) language enhancements. This includes things like lambda expressions, automatic type deduction, smart pointers, and support for concurrency.Each topic covered in the book follows the pattern of introducing the concept, demonstrating how to implement it, and explaining how it works. Additional information is provided on more advanced uses of the topic and sources for further information.This book is a valuable asset for anyone with a need to use the modern features of C++ in the context of system programming for Linux and other POSIX-compliant operating systems. Highly recommended!
    Amazon Verified review Amazon
    Karen Mar 19, 2021
    Full star icon Full star icon Full star icon Full star icon Empty star icon 4
    I've enjoyed a lot the good overview the author gave by covering (almost) all the aspects of the system programming. The examples (although basic) help to have a good grasp of the topic.
    Amazon Verified review Amazon
    S. Ghiassy Mar 12, 2021
    Full star icon Empty star icon Empty star icon Empty star icon Empty star icon 1
    i only found maybe 10 pages of this book useful and taught me something the rest is just crap. By its structure is obvious that the author just wanted to make pages by being repetitive about the running instruction. Total waste of money.
    Amazon Verified review Amazon
    Get free access to Packt library with over 7500+ books and video courses for 7 days!
    Start Free Trial

    FAQs

    How do I buy and download an eBook? Chevron down icon Chevron up icon

    Where there is an eBook version of a title available, you can buy it from the book details for that title. Add either the standalone eBook or the eBook and print book bundle to your shopping cart. Your eBook will show in your cart as a product on its own. After completing checkout and payment in the normal way, you will receive your receipt on the screen containing a link to a personalised PDF download file. This link will remain active for 30 days. You can download backup copies of the file by logging in to your account at any time.

    If you already have Adobe reader installed, then clicking on the link will download and open the PDF file directly. If you don't, then save the PDF file on your machine and download the Reader to view it.

    Please Note: Packt eBooks are non-returnable and non-refundable.

    Packt eBook and Licensing When you buy an eBook from Packt Publishing, completing your purchase means you accept the terms of our licence agreement. Please read the full text of the agreement. In it we have tried to balance the need for the ebook to be usable for you the reader with our needs to protect the rights of us as Publishers and of our authors. In summary, the agreement says:

    • You may make copies of your eBook for your own use onto any machine
    • You may not pass copies of the eBook on to anyone else
    How can I make a purchase on your website? Chevron down icon Chevron up icon

    If you want to purchase a video course, eBook or Bundle (Print+eBook) please follow below steps:

    1. Register on our website using your email address and the password.
    2. Search for the title by name or ISBN using the search option.
    3. Select the title you want to purchase.
    4. Choose the format you wish to purchase the title in; if you order the Print Book, you get a free eBook copy of the same title. 
    5. Proceed with the checkout process (payment to be made using Credit Card, Debit Cart, or PayPal)
    Where can I access support around an eBook? Chevron down icon Chevron up icon
    • If you experience a problem with using or installing Adobe Reader, the contact Adobe directly.
    • To view the errata for the book, see www.packtpub.com/support and view the pages for the title you have.
    • To view your account details or to download a new copy of the book go to www.packtpub.com/account
    • To contact us directly if a problem is not resolved, use www.packtpub.com/contact-us
    What eBook formats do Packt support? Chevron down icon Chevron up icon

    Our eBooks are currently available in a variety of formats such as PDF and ePubs. In the future, this may well change with trends and development in technology, but please note that our PDFs are not Adobe eBook Reader format, which has greater restrictions on security.

    You will need to use Adobe Reader v9 or later in order to read Packt's PDF eBooks.

    What are the benefits of eBooks? Chevron down icon Chevron up icon
    • You can get the information you need immediately
    • You can easily take them with you on a laptop
    • You can download them an unlimited number of times
    • You can print them out
    • They are copy-paste enabled
    • They are searchable
    • There is no password protection
    • They are lower price than print
    • They save resources and space
    What is an eBook? Chevron down icon Chevron up icon

    Packt eBooks are a complete electronic version of the print edition, available in PDF and ePub formats. Every piece of content down to the page numbering is the same. Because we save the costs of printing and shipping the book to you, we are able to offer eBooks at a lower cost than print editions.

    When you have purchased an eBook, simply login to your account and click on the link in Your Download Area. We recommend you saving the file to your hard drive before opening it.

    For optimal viewing of our eBooks, we recommend you download and install the free Adobe Reader version 9.

    Modal Close icon
    Modal Close icon