As a VS begins to respond to requests, new sockets, processes, and IPC resources may be created. Each of them must be associated with a VS because they incur system load and are used to relay work. Usually these new members are not added explicitly since the administrator does not even know of their existence and the application does not cooperate with the VS abstraction. Therefore, membership for these new entities is implicitly determined by the classification rules in the creator's VS descriptor.
Not only do new entities need to be associated with a VS, but VS-membership may also change over time. For instance, if some process is observed to be operating on a particular data set that is characteristic of some separately-managed VS, the process is added to that VS and removed from its current VS.
Classification, i.e., associating an OS entity with a VS, takes place
when the OS can infer something about the application, i.e., at system
call time. We can limit VS-membership inference to those times because
we assumed in Section 3.1 that
VSs interact with each other over a limited set of OS mechanisms. This
means that the works-for relation cannot change unless a system
call is invoked. Therefore, there is no need to update VS-membership at
any other time.
The classification rules that the OS examines at system call interception consist of a conditional clause, which defines when the classification rule is applicable, and a classification directive. This is formalized as:
Conflicting rules: Rule matching can lead to ambiguity. Multiple condition tuples may match the current system call interception. To solve this problem, VSs are prioritized. The rule that matches the highest-priority VS explicitly is used to determine the resulting classification. Should there be a tie between several rules, the most specific rule is applied. If this does not resolve ambiguity, the result is unspecified.
In the remainder of this subsection, we will discuss the different types of classification triggers. Table 2 casts common UNIX system calls into these categories.
Creation: If an entity, A, creates another OS entity, B, B's future VS affiliation depends solely on A's VS affiliation. Examples are the creation of sockets, IPC shared memory segments, message queues, pipes, and the like. The canonical default rule is for the created entity to inherit its creator's VS affiliation.
Communication: Communication is used to relay work within and beyond machine boundaries. Therefore, intercepting intra-VS communication is essential to VS maintenance in server farms. If it is possible to determine the VS affiliation of each request that is picked up by a service, the resulting activity can be charged to the correct VS. This does not depend on whether the request originated locally or remotely.
Communication affects at least three entities: sender, receiver, and the message itself. To make inter-process communication more efficient, most OS's implement asynchronous communication as opposed to the rendezvous concept. This adds sockets, pipes, and the like to the set of affected entities, each of which may be reclassified upon system call interception.
Due to the temporal separation between sending and receiving a message, pausing to reclassify the affected entities is difficult. Therefore, communication-based VS tracking is done in two stages. First, when the message leaves the sender it is tagged with a VS affiliation, much like what is done in the case of creation-type calls. This can be skipped if the communication is a one-to-one connection. In this case, the connection itself is labeled at setup time with a VS affiliation that implicitly applies to each message that passes through it. The second stage is message consumption. At this time, the receiver's VS affiliation may change based on its previous VS affiliation and the received message's VS affiliation.
Synchronization: The set of affected entities in synchronization includes the executing process(es) and all process(es) in the wait queue for the synchronization primitive. Activities that are performed under the protection of a synchronization primitive may be associated with its VS.
Synchronization can also be used to infer collaboration among a set of processes. Previously-unclassified processes may inherit the VS affiliation of the synchronization primitive. This is an effective tool since many multi-threaded server applications expose their process sets when they synchronize for thread control purposes.
The process(es) that execute under the protection of the synchronization primitive must not stall processes in the wait queue because otherwise, priority inversion [13] will result. This is also a problem when a single-threaded sub-service is shared among several VSs. This will be discussed further in Section 4 (accept).
Transformation: Whenever the kernel intercepts a characteristic argument to a system call, it is possible to classify the caller and other affected entities more accurately. For instance, the program name in the exec-call allows a more accurate VS classification of the active process if the program is typical of a specific VS. Other frequently-used system calls that may alter VS classifications without relaying work are setgid, setpgrp, and setuid.