Many of those things are already happening outboard anyway - all those
things have processors in them.
You don't have to look to "peripherals" to find additional processors.
Many NICs are now implemented as CPUs. Ditto video subsystems (GPUs,
of course). The keyboard *interface* on the original PC was a microcontroller.
Ditto sound subsystems, etc.
What the CPU is doing is largely managing
the data transfer to and from the device. eg the printer speaks PCL or
Postscript and the OS's workload is limited to firing the job at the printer
(USB/network) and the printer's CPU then decides where to put the ink on
the page.
You can delegate that management oversight to another core if you like, but
then you need management oversight of *that* core.
Specialized processors (co-processors, if you will) are usually optimized for
specific sorts of uses. The CPU in a NIC is probably piss poor at doing
floating point math!
Windows problems :-) But many of those things don't need to take much CPU -
they're ready to handle print jobs when you press Ctrl-P, but the rest of
the time they're ticking along in the background not taking much resources
because they don't need them.
It's "good design". Folks who write "one big program" are living in the 60's.
Your goal (for reliability and correctness) is always to compartmentalize and
reduce (in complexity) "tasks". Reduce the amount of sharing AND make it
very visible: global variables are the sign of an immature development
style (how do you know ONLY the "right" accesses are happening? why
SHOULD a particular activity NEED to see some datum?)
We have interrupt service routines. Aren't they essentially separate
processes?
For more than 40 years, I've used a supervisory process per each ISR;
NOTHING should be talking to the ISR besides that process ("discipline")
This sort of structure makes it easy to impose additional layers
of functionality on those resources.
[E.g., in the days of serial terminals, how could you ensure the current
time of day would be displayed in the lower right corner of the screen
if "anybody" could push characters out the serial port? If, instead,
you require them to go through an agent, then you can have that agent
present a "message oriented" interface and have *it* systematically
access the underlying driver/ISR]
The OS is running thousands of kernel threads, but they're mostly blocked
(not scheduled) until they need to do something. One thread per 'thing',
more or less. All that thread needs is a few hundred bytes for its register
state so the impact is small.
But, threads share an address space. So, can screw with each other.
A cleaner, more robust design is to use separate process containers
for each "thing". So, your network stack can;t screw up your
file system code.
[I think the average Linux release now contains over 1000 bugs! Had
they shifted to FIXING things instead of adding and refactoring,
they could actually improve the quality of the codebase! Ah, but
we can adopt the MS philosophy of just pushing out updates every
week or two! "Mr Smith, could you please bring your vehicle in
for service this week? We'd like to upgrade the brakes to
reduce your stopping distance. And, while we're at it, also
fix something we broke on your previous visit, LAST week!"]
[[I love this: <
https://lwn.net/Articles/914632/>
"Also noteworthy is 96c8395e2166 ("spi: Revert modalias changes"),
which deleted six lines of code and has required 24 fixes thereafter."
20 years later and they're still finding bugs in THAT release??]]
[[[Yet another: <
https://stack.watch/product/linux/> Note
that vulnerabilities may include *design* flaws and not just
"bugs"]]]
We have delightful hardware available, nowadays. And, affordable.
You no longer have to worry about whether to use a MPY opcode
or have to write a mult() routine. And, can use floating point
almost as easily as integer and fixed point math. You can
use virtual memory, EDAC to improve hardware "reliability",
isolated process containers, etc.
Yet, people still obsess over "make it faster". Um, how about make
it RIGHT, first? Lots of "best practices" have performance hits
(e.g., isolated process containers, lack of globals, capability
based designs, etc.) but dramatically increase the quality of the code.
Yet, folks still opt for fast-and-broken over slowER-and-correct!
Really, how many orders of magnitude FASTER does the hardware
have to get before you stop obsessing over speed? Does the
PRODUCT COST of a system vary THAT much that saving a few pennies on
a slower processor is really going to translate to additional
sales or profits? What cost do you associate with (lack of) quality?