Figures in LaTeX documents (what to use?)

Aug 13, 2026 Last reply: 3 weeks ago 54 Replies

CPUs used to be expensive so had to be shared and later threaded among both the bits of the OS and among user apps.

Times have changed. Basic OS architectures haven't.

John Larkin Highland Tech Glen Canyon Design Center Lunatic Fringe Electronics

If you use separate CPUs for each task you will be faced with huge interconnect problems and extra hardware stuff.

You still use BASIC. Ever written threaded code in C? No I do not mean your workers, but you? If not, your clue?

It is interesting how many tasks run on my Raspberry Pis at the same time.

One records 6 security cameras and 2 audio tracks, radiation, weather sensors, air traffic, other sensors, more things, CPU is not even fully loaded, plays music too.

Linux is co-operative development. Constructive team work has been around for several thousand years.

This rather misses the point that Unix was developed in a commercial environment, and Linus Torvald Linux developed it further in a cooperative and non-commercial environment. This is a "blind men describing an elephant" kind of reaction.

In fact the development of Unix was strikingly idiosyncratic, even for Bell Labs.

formatting link
formatting link
<snipped even more irrelevant comment>

UNIX was an outdated design when it was created. There were better systems on which to develop and better OS concepts to implement. UNIX was a quick hack to let folks get down to writing "applications" -- without worrying about the reality of security, the cost of bugs, etc.

It, much like MS, has likely hampered the design of better systems more than it has advanced the state of the art. The fact that software "accuracy" (getting what you set out to design), reliability and security haven't substantially improved with ANY of these platforms indicates the underlying concepts are a big part of the problem.

Sort of like using the same internal combustion engine concept and wondering why fuel efficiency, pollution, reliability, cost, etc. haven't made dramatic strides.

I'd been working on IBM systems before I discovered UNIX. The interactive edting environment was WYLBUR and it had a concept of exec files -similar to shell scripts- to automate simple things. For more serious work, there were compilers and batch processing, using JCL. Interactive sessions, using TSO, were only for a privileged few.

UNIX was a revolution. Everything was interactive. No JCL, no batch processing. You run a program just by typing its name. That included compilers. The compiler output became a new command, again run just by typing its name. It had an on-line manual and things behaved like it said. I/O was simple. Everything is a file. You open it, read or write it, close it. Simple. No weird DISP, SPACE, RECL, BLKSIZE, etc, it just worked.

You could even run multiple programs at once, or pipe together several to do more complicated things. I was instantly sold, no more IBM for me. UNIX was bliss.

Jeroen Belleman

Jeroen, you are absolutely right!

Has there surfaced anything better, ever?

VM/370, CMS, the grumpy operator you had to hand over your Spice card decks for the CDC6600/Cyber176? RSX-11, VAX/VMS, DEC system10? The Hurd, which is the biggest thing in our future since sliced bread, for 25 years now?

UCSD was at least some fun at home. And I had quite a nice T800 transputer cluster with OCCAM.

And yes, I did a Z8000 port of Andrew Tanenbaum's Amoeba kernel & EM, but where is Amoeba now? I was a devoted fan of AT, very close to follow him to Amsterdam.

cheers, Gerhard

Humans don't interact with operating systems so all of your examples are misplaced.

An operating system manages resources FOR PROGRAMS. When YOU interact with a computer, it is through some "utility program" that aims to provide an interface to some aspect of the machine that is relevant to you, as a human.

You certainly wouldn't consider MineSweeper part of an operating system called "Windows". Nor would you call DIR, ERASE, ls(1), rm(1), mv(1), etc. They are convenience PROGRAMS to provide a human user with some tools to interact with some ASPECT of an operating system (e.g., the filesystem).

This has occurred because of the weenification of terminology where supermarket clerks refer to "operating systems" with their attendant level of inexperience.

You might gripe about how those PROGRAMS work but likely are clueless about how memory is managed, how pages are selected to be swapped to secondary storage, how packets are scheduled for transmission over the network, etc. These are facilities that the OS provides TO THE PROGRAMMER.

The fact that you might reference ../FRED/TAXES as SET DEF [-,FRED,TAXES] in VMS or ..\FRED\TAXES in DOS/Windows or <FRED>TAXES in MULTICS is a consequence of the command set that you are presented with. These *conventions* can be changed -- as long as the pathnames passed to the appropriate APIs follow the rules established for them.

E.g., I can create a filename "**I*really*like*asterisks**" if I make a special effort to do so -- because '*' has no special meaning in a filename but, rather, to the PROGRAM (or shell, as the case may be) with which a user would interact.

The desirable advances in an OS -- ignored in UNIX's design -- pertain to the environment that the PROGRAM (and programmer) encounters. Anything presented to the user is built on top of that and could easily be changed (but, you can't change how packets are scheduled on the network interfaces without altering the OS itself) as part of the userland.

The OS determines what you CAN do; programs running under it just impose additional restrictions/shortcomings. Try to put two programs in isolated containers in DOS and you'll realize that DOS doesn't support this abstraction.

Complaining about something that is exposed to the user is a distraction; you can distribute a UNIX-based product that doesn't have /bin, /sbin, /usr, etc. and it will still *behave* like UNIX. (what need does an appliance have for all of the PROGRAMS in those parts of the hierarchies??)

The reason "new" ideas don't get adopted is inertia; too much code built on old models and fear of moving away from them. Better to live witht he flaws in teh old than *avoid* them in something new, eh?

Sorry Don, but that's tripe. Rather than hamper, unix inspired a whole generation of operating systems, many of which flourish to this day, including Linux. Of course, the latter has deviated significantly from the original ideas of sound software engineering practice. I think you need to discard the bias, and do a bit more reading.

Real time os work here primarily, for decades now, with many of the rtos systems closely modelled on unix fundamentals. Have a look at rtos like VxWorks, if you want evidence.

Chris

What I don't understand, is why you specify an expensive op amp to use as a comparator, when perhaps a single quad comparator like an LM339, could get the job done more cheaply, and take up less board space.

Seems like the the whole project is being overthought, with a gate array, complex internal logic for debounce, when a cheap single chip micro, could get the job done in a few pages of code, and far less complexity.

Chris

It also KILLED many far better ideas regarding the design of operating systems and the systems built on them.

Has the rate of BUGS gone down? Is it easier for less skilled people to produce working, bug free, secure products? Or, are we still living in the 1970's when it comes to quality?

formatting link
*Fifty* years of real-time product design, here. And, considerable amounts of time exploring different hardware and software technologies over that span.

Why should a program know about every named object in a system? I.e., the single, shared filesystem namespace? Do you put all of your variables and other identifiers as GLOBALS in your codebase? Of course not! Doing so is A Bad Idea.

UNIX cheaped out on protections for named objects (user, group, other) as it found ACLs too expensive. And, ACLs are much more limited than a capability-based approach (available in Hydra which was contemporary with UNIX); UNIX just didn't think security was important.

MULTICS provided run-time hardware replacement -- still not really possible with UNIX-derivatives (cave for maybe hot-swap drives). Nor can you replace/upgrade a software library (or service) WHILE it is being used.

All old ideas that were sidelined in favor of something inferior.

I stand by my comments. Glad you're enjoying the 1970's nostalgia that you've saddled yourself with.

Sometimes. But more often, I use kids and Python.

I recently did a signal synthesis model with a mix of PowerBasic and LT Spice. LT is dreadful at digital stuff. Apparently QSpice is better.

The advanced versions of Basic were great: Basic+ and PowerBasic. Basic suffered from snobbery among people who like their code to literally look like code.

I had an intern (actually a grandson) who did a cool app in VisualBasic in literally minutes.

I think I've written two simple programs in c.

c is ugly.

The best way to program is to hire kids to do it. Lately, they use AI.

I'd rather invent things and design electronics. Solder, don't type.

We have a new product line based on the RP2040 chip. The 2040 is wonderful; they did most everything right, for 75 cents. It's now officially OK to overclock the 2040 CPUs to 200 MHz.

formatting link
Both boards are rev A, first try. Both work without mods. We might change one resistor to balance some power dissipations.

John Larkin Highland Tech Glen Canyon Design Center Lunatic Fringe Electronics

We like to minimize BOMs, and I needed opamps elsewhere.

An ancient 339 wouldn't work well. We want RRIO with a 3.3v supply. A

339 would need output pullups. Rise times would be even slower, so we'd want to debounce in the FPGA too.

The tach stuff is a baby board bolted into a host module. The host has PoE power, ethernet, USB, a Pi uP, and an FPGA.

The FPGA logic is easy. In production, features are free.

John Larkin Highland Tech Glen Canyon Design Center Lunatic Fringe Electronics

Software is still barbaric. I expect things to get a lot better in 10 or 20 years.

Car engines are vastly better than they were even 50 years ago. Far cleaner and more reliable and more powerful.

I used to change the oil and filter every month, and cars were always beaking. Now I get my Audi serviced once a year.

John Larkin Highland Tech Glen Canyon Design Center Lunatic Fringe Electronics

We've been writing software, of one sort or another, since the late

1940's. The computers have got a lot faster since then, and go in for longer words. That's nearly 80 years now. Why do you expect things to get a lot better in the next ten to twenty years?

Artificial intelligence might get better at distilling the desired result out of natural language expressions of that desire, but it's more likely that natural language - which evolved to do lots of very different jobs - will have to change first.

Not a lot more powerful. The contact between the tyre and road limits the amount of power you can use. Smaller, lighter, faster-spinning engines can now generate that maximum useable power, and fast cheap little computers can optimise the process of generating the power and control gear like super-chargers that used to blow up a little too often.

It's not a comparable problem. Cars get you from one point to another. Computers get used to do all kinds of different jobs, some of which didn't exist before they were invented

And your electric car, when you move on, will be even less troublesome.

C is beautiful, close to the hardware too. Many very useful libraries exist in C, for example libmath libfft libforms (GUI in X) .. LIBRARY = $(X_CFLAGS) $(X_LIBS) -L/usr/lib/X11 -lX11 -L/usr/lib -g -O2 -lpthread -lforms -lm -lXpm -lcrypt -lfftw3 -lrtlsdr

And portability, The gcc compiler exists for several platforms, even had C80 for my Z80 system.

I recommned reading Kernighan and Ritchy 'The C programming language'

formatting link
do some coding.

ASM is fun too, you need to know the hardware, using it for Microchip PICs, some other micros.

I think long ago I was reading Dr Dobbs magazine, an article about linked lists, could have been this one:

formatting link
? I use linked list in many things since that article, including in this Usenet reader.

Yes, soldering I do too, I use 60/40 though.

formatting link

formatting link
formatting link
working!

As hardware changes, programming in C saves a lot of time and makes your code portable.

Invent things? Maybe the anti-gravity drive? (need a few million .. LOL... But maybe ... Was just reading China just now did a space rocket landing using landing legs:

formatting link
Did you buy SpaceX shares?

Build your own sat and China will put it in orbit for a few dollars for you?

I mentioned the 339 as an example, sure there are better and more modern substitutes.

But look, take a random sample of experienced developers and ask how many are familiar with vhdl, whatever,and how many are familiar with C. All you are doing with this, is replacing the software development in C, with VHDL, whatever. In terms of future maintainability, change and and access to skills, a C solution must make more sense. With the ever increasing performance of current micros, there is no longer any need for gate arrays, other than for high speed designs, which this is not.

Chris

What bugs ?. I guess you must be talking about mainstream os like Windows and Linux, but they have become so complex, I suspect that there is no way to prove the overall effort is correct. Bits of old versions, new bits glued on all over the place, is not a recipe for success.

Software engineering has always required a disciplined approach, and there are no short cuts to produce stuff that works, and become proficient in the art. For those that can't be bothered, go flip burgers.

There really are limits in many subjects, in terms of how much they can become deskilled, before the output becomes garbage. The whole idea of computing, was to make it easy for the unskilled to get more work done, not enable understanding how the os works. Hiding the complexity, presenting a simple interface, is what its about at that level. But someone has to design and write the original code, so not worried about the effect that ai will have. Trillions put into it, and very little return so far. At least partly, just another pump and dump tech bubble.

I expect AI-like tools that let a person describe what they want done, and the tool generates the application. My guys are doing that already, and it's still early days.

Code nowadays looks like cats walking on keyboards, or building bridges from popsicle sticks. And people are still trying to invent "safe" languages!

My 3.2l AWD V6 rocks. It's rare that I want all that acceleration, but it's fun now and then.

No thanks. How's your electric car?

John Larkin Highland Tech Glen Canyon Design Center Lunatic Fringe Electronics

The OS exists for the convenience of the *programmer*. So, how many bugs has the design/model of the OS helped eliminate? How has it lowered the bar for developers (programmers) to produce quality code that meets its design goals?

As long as you aren't perpetually REbugging the OS, it's performance can become a known. Thus enabling developers to concentrate on getting THEIR code correct.

Exactly. But, no one wants to revisit the design/model because they have too much invested (personally and institutionally) in that "codebase".

If you look at other options that have come (and gone?) over the years, you can see that there have been many "better ideas" that simply never saw enough support to merit continued presence in the marketplace.

Hydra, Alpha, VRTX, ThreadX, pSOS, CTSS, MULTICS, Jaluna, Inferno, RTEMS, Mach (3/4), L4, Plan 9, MCP (yes, it wasn't just a movie prop), EROS, Chorus, QNX, Amoeba, KeyKOS, Harmony, etc. all offered different visions of what the "machine model" should look like, to the programmer. The abstractions provided impact how the developer structures his/her code and the extent to which those abstractions are fully developed defines the extent of support the OS provides.

My RTOS is "decomposed" -- more like a microkernel than a monolithic kernel. I freely trade performance for correctness and model integrity. E.g., almost everything is an IPC/RPC (more exactly, RMIs). This coerces you to using call-by-value semantics. This, in turn silently protects the "item/value" that you are passing to the function from concurrent modification by some other thread in the same process container. Such races are next to impossible to find in the code and can remain dormant until the load factor increases to a point that causes scheduling of tasks to vary enough to break a region that *should* have been atomic (but the developer was negligent in enforcing such constraints).

I can move an object (EVERYTHING is an object -- including "programs") from one node to another node *while* it is executing. And, the target node need not be of the same hardware architecture. I can implement redundancy at any function call just by (silently) dispatching the call to multiple instances of the (micro-)service responsible for its implementation and then taking:

- the first result

- a concensus of results all without the developer having to change how his code is written.

A process need only know about the "things" that it needs to perform its function -- there is no "/etc/passwd" to be protected from nosey actors as there is no way to *reference * the "user database" if you have no need to do so! REGARDLESS OF THE UID UNDER WHICH YOU ARE EXECUTING.

Additionally, you only access the parts of the user database that you *need* to access. E.g., login(8) needs to test the cleartext password you've provided -- no need for it to *see* the encrypted password. Or, the location of your $HOME. Or shell. Or anything else that might want to be encapsulated in the "user database" (groups in which you have membership?). You ("program") have capabilities that are assigned to you at design time so that you CAN access those things -- and ONLY those things. No need for the guy who wrote login(8) to be able to poke around in folks' MBXs!

And, as the "capabilities" that you need are known at design time, if you try to do something for which you haven't been granted a capability, the OS *knows* you are:

- broken

- malevolent so need not hesitate to abend and forever prohibit you from EVER being loaded, again! (important if you allow foreign code into your product -- "Why are you trying to access /etc/passwd?")

I track resource usage so I know your "cost" to the system at this point in time. If the system goes into overload, I can then decide which processes to terminate to bring the available resources in line with the demands for those resources.

As its an RTOS, there are specific DEADLINES for each process. So, the OS can look at the runnable tasks and decide if some simply won't meet their deadlines and terminate them NOW --so other tasks might meet their deadlines (instead of risking ALL missing EVERY deadline).

[How many "RTOS"s actually allow deadlines to be specified and used in scheduling decisions? How much is just HOPING the tasks complete before the deadlines that the developer has in the back of his mind? What happens when other code is added to the system -- instead of a closed-box design?]

Etc.

None of these are new ideas. Yet, folks typically have no experience with them because they have been coerced into using *an* old OS design.

[Yeah, you can find things like RT and capabilities BACKPORTED to current OS offerings. But, they are afterthoughts and, as such, usually don't "fit" as well as if they had been in place from conception.]

Imagine what the state of the art in OSs would be had something more capable than UNIX been used as the basis...

But an OS can make the developer's life SO much easier. And, the resulting products much easier to AUDIT (security). They can be smaller and more focused, reducing the amount of code that has to be examined/debugged/validated. Interfaces and interconnects to the rest of the system are more visible (you have to explicitly define a need for a capability in order to be given it; you can't just TRY to access something as your attempt will fail AND be seen as an indication of a bug/exploit).

Additionally, outstanding capabilities act as reference counters so you can automatically determine when an object has exceeded its lifespan ("No one else holds a capability for this object so I can release ALL of the resources that it requires -- including any references to OTHER objects that it might hold")

And, this can all be "automatic", not requiring any conscious effort from the developer!

E.g., each process is given a namespace (in lieu of stdin, stdout, stderr as those CONCEPTS may not apply to the role the process plays). One of the "best practices" is for a process to resolve the names that are hardcoded into it at startup by invoking: MyNamespace.resolve(SOME_NAME) and binding the result to a variable that it will thereafter use in the code. Much like opening a file and using the filehandle, thereafter (having deliberately "FORGOTTEN" the actual name of the file!)

Once the process has bound each capability (the result of the "resolve") to an internal variable that will thereafter be used to access THAT object, the namespace is no longer needed. So, the resources used by the namespace (and the member functions that access/manipulate it) can be shed.

In UNIX, Windows, etc. the resources will likely EVENTUALLY be moved out to swap (or the paging file). But, they are still consuming resources, even though you (the developer) know that they will NEVER be revisited! You "save" the effort of swapping them out AND the store required to hold them on the assumption that they WILL be referenced, again. If the OS will potentially opt to kill off processes to trim resource usage, would you want to be "charged" with a resource that you KNOW you aren't really using?

But, the *developer* is expected to understand these things -- being "skilled".

One of my favorite interview questions is: Pick the better implementation

for (r=0 to ROWMAX) for (c=0 to COLMAX) do_something(array[r][c])

for (c=0 to COLMAX) for (r=0 to ROWMAX) do_something(array[r][c])

A "programmer" sees no difference (assume do_something has no side-effects or dependencies other than the operation it performs on the array element). The OS *hides* that difference so the developer need not be concerned with it IN CASES WHERE THE ACCESS PATTERN HAS DELIBERATE SIGNIFICANCE.

As a practitioner of the art, one should WANT his tools to enable him to produce the best product possible. That's what moving from my "pocket assembler" for the i4004 -- a crumpled up sheet of well-used paper that tabulated the formats for each opcode so I could "write machine code" (NOT assembly language!) for the product -- to HLLs that let me just express abstractions and a *tool* does all the s*it work FOR me. So I can concentrate on the problem and not the tool.

The colleagues with which I share my codebase initially disliked my approach. But, that was out of laziness: "why do we have to learn a NEW way to do the same old thing?" Once they realized it was NOT "the same old thing" and the power afforded to them in creating their specific applications, the objections were replaced with praise: "Wow, I didn't realize that free'd memory came back CLEARED and TESTED! And, memory found to be defective was automatically sequestered so I don't have to worry about code or data being corrupted!"

Providing these services to the developer frees him from having to implement them (or, rationalize NOT implementing them in an attempt to trim his efforts)

There's a real difference between VHDL and C and it is the difference between a single processor - which can do one thing at a time - and a logic array which can support simultaneous parallel processing.

Gate arrays make sense anywhere you need multi-thread parallel processing.

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required