The main reason for using processes is that the process may crash or crash, and the OS will limit the effect of this on other processes. For example, Firefox recently started running plugins in separate processes, IIRC Chrome launches different pages in different processes, and web servers process separate requests in separate processes for a long time.
There are several different ways to apply OS restrictions:
- Crash - as you noticed, if the thread crashes, it generally removes the whole process. This motivates the boundaries of the browser process: browsers and browser plug-ins are complex bits of code that are subject to constant attack, so it makes sense to take unusual precautions.
- Resource limits. If a thread in your process opens a lot of files, allocates a lot of memory, etc., then this affects you. Another process is not needed, as it may be limited separately. Thus, each request on the web server may be more limited in resource use than the server as a whole, because you want your server to serve several requests at the same time without any remote user resources.
- Opportunity. It depends on the OS, but for example, you can run the process in the chroot prison to make sure that it does not modify or read files that it should not, no matter how vulnerable your code is to use. In another example, SymbianOS has an explicit list of permissions for performing various actions with the system ("read user phone book", "write user phone book", "decrypt DRM files", etc.). It is not possible to give up access rights to your process, so if you want to do something very sensitive and then return to low sensitivity mode, you will need the process border somewhere. One of the reasons why you need to do this is security - an unknown code or code that may contain security flaws can be somewhat isolated, and a smaller amount of code that is not limited can be examined more closely. Another reason is to get the OS to fulfill certain aspects of your design.
- Drivers In general, a device driver controls sharing of a unique system resource. As with features, restricting this access to a single driver process means that you can restrict it to all other processes. For example, IIRC TrueCrypt on Windows installs a driver with advanced permissions, allowing it to register an encrypted container with a drive letter and then act like any other Windows file system. Part of the GUI application runs in normal user mode. I'm not sure if the file system drivers in Windows really need a process associated with them, but device drivers as a whole can do this, so even if this is not a very good example, we hope this gives an idea.
Another potential reason for using processes is that it makes it easier to explain your code. In multi-threaded code, you rely on the invariants of all your classes to infer that access to a specific object is serialized: if your code is not multi-threaded, you know that it is [*]. Of course, this can be done with multi-threaded code, just make sure you know which thread "owns" each object, and never access an object from a thread that does not own it. The boundaries of the process provide this, and not just design for it. Again, I’m not sure that this is motivation, but, for example, a World Community Grid client can use several cores. In this mode, it starts several processes with a completely different task in each, therefore it has the performance advantages of additional cores, without the need for separate parallelization of a separate task or code for any task that should be thread safe.
[*] Well, if it was not created in shared memory. You also need to avoid unexpected recursive calls, etc., but this is usually a simpler problem than synchronizing multi-threaded code.
source share