|
This is very common when controlling equipment in C++. Technically, all C++ programs control equipment. Differences include that one program may run for weeks or even years, and is mostly the only program running, or the only one on a core. This happens from microcontrollers on up to servers with a TB of RAM running, say, high-frequency trading, and in networks of hundreds of those, running weather simulations. The program typically does all its heap allocation at startup. There is no reference-counting std::shared_ptr. You might have lots of std::vector<std::unique_ptr<T>>, std::string, the works, but they all get provisioned in the first second or two, and then just used thereafter. If anything goes wrong, you don't try to do anything clever or sophisticated; you just kill and restart, or even re-boot, and start over from scratch. That is fine if it doesn't happen too often, so you make sure it doesn't. For communication between programs, some of the memory set up is shared, with a header containing std::atomic<std::uint64_t> sequence counters that each process can watch and compare against its last copy to know when something changed. Most commonly, actual messages show up on a ring buffer, so you don't need to act on them immediately; as long as you pick them up before they get lapped, you're good. If you get lapped, you might need to reset the whole system; so you make sure not to get lapped, by making the ring buffers big enough and by picking up messages soon enough. With big enough ring buffers and careful scheduling, you can leave all the bulk data there and just use it before it gets overwritten, avoiding expensive copies. Often, once the program starts up, it does no more system calls at all, doing all its work by reading and writing shared memory, and maybe poking at hardware registers. On Linux one usually isolates cores doing this, with "isolcpus=..." on boot, and "nohz_full=...", "rcu_nocbs=...", "rcu_nocb_poll" etc. The ring buffers tend to live in hugepages ("hugepages=50000"), often just files opened in /dev/hugepages. This is all a simpler alternative to a unikernel/parakernel/demikernel/blatherkernel. You might also have ephemeral processes that run just long enough to do a job and then quit, running on their own pool of cores and using their own pool of memory. This is usually how you administer the system: ssh in, look around, exit. |