I first encountered DOS/360 on a System/360 model 25 with 48K of
memory. This was a one-job-at-a-time batch system, but the I/O
primitive (EXCP--execute channel program) was asynchronous. So I
don't think the small memory rationale really applies.
Hrrmpt... it was single task. Being asynchronous in the I/O and allowed process asynchrony takes a lot more housekeeping. Paul you know I agree with you, it was always an issue with UNIX IMO. The problem is how to do it differently.
At Masscomp RRU, our solution was not to try to 'fix it' as much as add a new scheme beside the synchronous one. We added a general AST's mechanism that anyone could use (very much like RSX and VMS in semantics), but left signals alone. We added new async calls, which were just implemented via ioctl's (the universal hack) for the specific HW that supported it. In retrospect, that was an error, it should have been aread(2)/awrite(2) and then added the completion routine/call back as the 4th & 5th parameters. Since Stellix was not Real-Time, we left them out. [ tjt and I have argued about that for years ].
So back to Doug/Dan's answer -- I think for a small system, like the original PDP-7 and the PDP-11/20 putting the effort to make it multiprocess and leaving the I/O synchronous definitely made it easier. Particularly, since what was created with the signal semantics. To me, UNIX got way more right than wrong. I suspect if signals had been more like AST's, the idea of being async might have gone farther. But to use Dennis's like about C being quirky, signals are very quirky. wnj tried to 'fix' them and frankly it just made matters worse. And IMO, signaction(3) as Doug says, is a nightmare.
I've generally been a fan of introducing a new idea separately as a 'stronger strain' and then seeing if people likely it.
FWIW: A couple of us did try to get AST's into the POSIX.4 (they were there in a draft), but ultimately *.4 was rejected as 'not UNIX.'