blob: 4baeff3b29baf4911250b9feb009f69d7407be41 [file] [log] [blame]
Mike Frysingere8ad4632010-08-17 18:18:35 -04001-------------
2--- Intro ---
3-------------
4
5Linux running on processors without a memory management unit place certain
6restrictions on the userspace programs. Here we will provide some guidelines
7for people who are not familiar with such systems.
8
9If you are not familiar with virtual memory, you might want to review some
10background such as:
11 http://en.wikipedia.org/wiki/Virtual_Memory
12 /usr/src/linux/Documentation/nommu-mmap.txt
13
14----------------------------
15--- No memory protection ---
16----------------------------
17
18By virtue of every process getting its own virtual memory space, applications
19are protected from each other. So a bad memory access in one will not affect
20the memory of another. When processors forgo virtual memory, they typically
21do not add memory protection back in to the hardware. There are one or two
22exceptions to this rule, but for now, we'll assume no one supports it.
23
24In practical terms, this means you cannot dereference bad pointers directly
25and expect the kernel to catch and kill your application. However, you can
26expect the kernel to catch some bad pointers when given to system calls.
27
28For example, this will "work" in the sense that no signal will be sent:
29 char *foo = NULL;
30 foo[0] = 'a';
31 foo[1] = 'b';
32
33However, the kernel should return errors when using "standard" bad pointers
34with system calls. Such as:
35 char *foo = NULL;
36 write(1, foo, 10);
37 -> kernel will return EFAULT or similar
38The other bad pointer you can rely on in your tests is -1:
39 char *foo = (void *)-1;
40 read(0, foo, 10);
41 -> kernel will return EFAULT or similar
42
43Otherwise, no bad pointer may reliably be tested, either directly or
44indirectly via the kernel. This tends to be a large part of the UCLINUX
45ifdef code that shows up in LTP.
46
47----------------
48--- No forks ---
49----------------
50
51The ubiquitous fork() function relies completely on the Copy On Write (COW)
52functionality provided by virtual memory to share pages between processes.
53Since this isn't feasible without virtual memory, there is no fork() function.
54You will either get a linker error (undefined reference to fork) or you will
55get a runtime failure of ENOSYS.
56
57Typically, fork() is used for very few programming paradigms:
58 - daemonization
59 - run a program
60 - parallelism
61
62For the daemonization functionality, simply use the daemon() function. This
63works under both MMU and NOMMU systems.
64
65To run a program, simply use vfork() followed by an exec-style function.
66And change the error handler in the child from exit() to _exit(). This too
67works under both MMU and NOMMU systems. But be aware of vfork() semantics --
68since the parent and child share the same memory process, the child has to be
69careful in what it does. This is why the recommended construct is simply:
70 pid_t child = vfork();
71 if (vfork == 0)
72 _exit(execl(....));
73
74For parallelism where processes use IPC to work together, you have to options,
75neither of which are easy. You can rewrite to use threads, or you can re-exec
76yourself with special flags to pass along updated runtime state. This is what
77the self_exec() helper function in LTP is designed for.
78
79-------------------------
80--- No overcommitting ---
81-------------------------
82
83Virtual memory allows people to do malloc(128MiB) and get back a buffer that
84big. But that buffer is only of virtual memory, not physical. On a NOMMU
85system, the memory comes immediately from physical memory and takes it away
86from anyone else.
87
88Avoid large mallocs.
89
90---------------------
91--- Fragmentation ---
92---------------------
93
94On a MMU system, when physical memory gets fragmented, things slow down. But
95they keep working. This is because every new process gets a clean virtual
96memory address space. While processes can fragment their own virtual address
97space, this usually takes quite a long time and a lot of effort, so generally
98it is not a problem people hit.
99
100On a NOMMU system, when physical memory gets fragmented, access to large
101contiguous blocks becomes unavailable which means requests fail. Even if your
102system has 40MiB _total_ free, the largest contiguous block might only be 1MiB
103which means that allocations larger than that will always fail.
104
105Break up your large memory allocations when possible. Generally speaking,
106single allocations under 2MiB aren't a problem.
107
108-----------------
109--- No paging ---
110-----------------
111
112No virtual memory means you can't mmap() a file and only have the pages read in
113(paged) on the fly. So if you use mmap() on a file, the kernel must allocate
114memory for it and read in all the contents immediately.
115
116---------------------
117--- No swap space ---
118---------------------
119
120See the "No paging" section above. For the same reason, there is no support
121for swap partitions. Plus, nommu typically means embedded which means flash
122based storage which means limited storage space and limited number of times
123you can write it.
124
125-------------------------
126--- No dynamic stacks ---
127-------------------------
128
129No virtual memory means that applications can't all have their stacks at the
130top of memory and allowed to grown "indefinitely" downwards. Stack space is
131fixed at process creation time (when it is first executed) and cannot grow.
132While the fixed size may be increased, it's best to avoid stack pressure in
133the first place.
134
135Avoid the alloca() function and use malloc()/free() instead.
136
137Avoid declaring large buffers on the stack. Some people like to do things
138such as:
139 char buf[PATH_MAX];
140This will most likely smash the stack on nommu systems ! Use global variables
141(the bss), or use malloc()/free() type functions.
142
143-------------------------------
144--- No dynamic data segment ---
145-------------------------------
146
147No virtual memory means that mappings cannot arbitrarily be extended. Another
148process might have its own mapping right after yours! This is where the brk()
149and sbrk() functions come into play. These are most often used to dynamically
150increase the heap space via the C library, but a few people use these manually.
151
152Best if you simply avoid them, and if you're writing tests to exercise these
153functions specifically, make them nops/XFAIL for nommu systems.
154
155-------------------------------
156--- Limited shared mappings ---
157-------------------------------
158
159No virtual memory means files cannot be mmapped in and have writes to it
160written back out to disk on the fly. So you cannot use MAP_SHARED when
161mmapping a file.
162
163-------------------------
164--- No fixed mappings ---
165-------------------------
166
167The MAP_FIXED option to mmap() is not supported. It doesn't even really work
168all that well under MMU systems.
169
170Best if you simply avoid it, and if you're writing tests to exercise this
171option specifically, make them nops/XFAIL for nommu systems.