The bigger problem is that the Raspberry Pico is a dual-core Cortex-M0+, which doesn't have an MMU, so it can't run Linux and especially can't handle fork(). But httpdito is basically scripting the Linux system call interface in assembly language—it needs to run on top of a filesystem, an implementation of multitasking that provides allocation of different memory to different tasks, and a TCP/IP stack. Any one of these is probably a larger amount of complexity than the 296 CPU instructions in httpdito.
The smallest TCP/IP stack I know of is Adam Dunkels's uIP. Running `sloccount .` in uip/uip cloned from https://github.com/adamdunkels/uip gives a count of 2796 lines of source code ("generated using David A. Wheeler's 'SLOCCount'."). uIP can run successfully on systems with as little as 2KiB of RAM, as long as you have somewhere else to put the code, but for most uses lwIP is a better choice; it minimally needs 10KiB or so. uIP is part of Dunkels's Contiki, which includes a fairly full-featured web server and a somewhat less-full-featured browser. I think he got both the server and the browser to run in 16KiB of RAM on a Commodore PET, but not at the same time.
(twIP http://dunkels.com/adam/twip.html is only 139 bytes of C source but doesn't support TCP or any physical-layer protocol such as Ethernet, PPP,or SLIP.)
However, Adam Dunkels has also written Miniweb http://dunkels.com/adam/miniweb/, which implements HTTP and enough of TCP and IP to support it, in 400 lines of C. It needs at least 30 bytes of RAM. Like twIP, it doesn't provide a physical layer. But that's solvable.
You say Linux won't work without MMU, it can't handle physical addresses? Moreover, why won't fork() work without MMU?
It's possible that there are deep assumptions in the Linux code that some fundamental software or hardware memory handling capabilities are present.
You also have no inter-process security, so everything can crash everything else including the kernel, and no swap.
It used to be the case that all Linux executables had to be loaded at the same virtual address, but ASLR may have removed requirements of this kind. https://stackoverflow.com/questions/38549972/why-elf-executa...
Maybe you mean that before ELF support, Linux a.out executables had to be loaded at a fixed virtual address? That's possible—I started using Linux daily in 01995, at which point a.out was already only supported for backward compatibility.
Pretty much, yeah.
> You say Linux won't work without MMU, it can't handle physical addresses? Moreover, why won't fork() work without MMU?
When httpdito fork()s two child processes, each of them starts receiving the HTTP request into the request buffer at `buf`. This works because the semantics of fork() give those two children two different buffers at the same memory address, one in each process's address space. The Linux userland relies relatively heavily on these semantics. It was a major obstacle to getting an SSH server running on cisco IOS, for example.
An event-driven server like darkhttpd is a much better fit for an MMUless system. Implementing multithreading is easy (it's half a page of assembly) but implementing memory mapping without an MMU requires some kind of interpreter.
(Actually you can implement fork() without virtual memory and without an MMU, for example with PDP-11-style segmentation, but the Cortex-M0+ doesn't have any of those facilities either.)
Can you elaborate on this? Hasn't Cisco IOS at various times run on MIPS and X86 processors?
I think running Linux on a Cortex-A is entirely normal, FWIW.