Friday, October 19, 2007

Files

One of the difficulties with multi-variant execution is file operation.
When variants try to open a file we can open the file in the platform and send the results to the variants. This solution fails if the variants try to mmap the file. They use a file descriptor that is sent to them by the platform and is not really open in their contexts. Therefore the mmap returns error. This situation happens frequently when variants map shared libraries.
Another solution is to open all files for all variants, but preventing them from writing to the files. We allow only one of the variants (or the platform) to write to a file. This solves the problem of the previous method and helps keep valid file descriptors in variants, but the locking mechanisms of the kernel don't allow us to open one file for writing in a few processes simultaneously.
An alternative solution is to open files that are opened as read-only in all variants and open the other files only in the platform. Obviously, this solution still has the problem of the first solution. Files that are not opened for all variants can not be mmapped, but it is not as severe as the former problem, because in most cases the files that are mmapped are opened as read-only and, therefore, are opened by all variants.
The only complication is that the files that are opened by the platform and those opened by the variants can have the same file descriptor. For example, a request to open file "a.txt" for reading and writing is received by the platform. The platform doesn't allow the variants to open the file and opens it itself. Let's assume it is assigned file descriptor #5. This file descriptor is sent to the variants and they use it when they request further operations on the file.
Now variants want to open "b.txt" as read-only. The platform let them run the syscall and open the file. This time they get the file descriptor directly from the kernel that can be 5 again! Now if they invoke "read" to read file descriptor #5, it will not be clear whether they want to read "a.txt" or "b.txt". To solve this problem, the platform adds a big number to all file descriptors that are opened by itself before sending them to the variants. In Linux 2.6, maximum number of files that can be opened by a process is 256 and therefore, the largest file descriptor is 256. If we add 256 to all file descriptors opened by the platform before sending them to the variants, we can distinguish between the files opened by the variants and those opened by the platform. Now all file operations requests sent by the variants that have a file descriptor larger than 256 should be performed on the files opened by the platform and those that have smaller file descriptors should be performed on the files opened directly by the variants.

No comments: