The web uses exact location names (which have no location tranceparency or independence except as implemented at a certain cite). The main advantage of this approach is that looking up a name is quick and easy.
Remote Procedure Call. RPC works by providing stubs at both the client and the server. The RPC services register with the OS, and then when the client makes the procedure/system call, the OS uses the client stub to send a message to the server stub, then the server actually does the work, and sends a message with the result back to the client.
CPU, seek time, rotational delay, and latency.
Kernel threads are known to the operating system, and thus the OS can reason about and schedule them even if other threads from the same process are doing I/O or are otherwise blocked. User threads are implemented in user libraries, and are unknown to the OS which means the user code can perform specialized scheduling algorithms for the particular application, but since the OS does not know about them the OS may pre-empt the process when one of its threads does I/O even when there are threads that can run.
Since performance is the main criteria, my web cacher is going to be user based, i.e., I will have a cache personalized to each user and her or his access patterns. This structure assumes plenty of spare disk space in which I can store my cache, with some limit L on the amount of disk space I can use for it.
To keep track of pages and their locality, the web cacher will keep a table of accessed web pages, hashed by the location name, for quick lookup. I will limit the size of the table to twice the size of the number of pages stored on disk to keep access times down. It will keep a pointer to an entry on a LRU list of all the web pages in order to quickly choose a replacement web page.
On an access to page, the web cacher will fork two threads: (1) the fast path thread (i.e., the one that keeps the processor) checks the web cache and if the page is in the cache, the web cacher displays it. The page can be in memory or it may need to be fetched from disk. A page fetched from disk is also put in memory. (2) The other thread initiates a remote fetch of the page. When the fetch returns, if there is no cached page, it caches this page. If the page is cached, it checks to see if the page in memory is correct, if it is not, it reloads the new version of the page to the web server and replaces the page in memory. This thread also always updates the LRU web page list. It looks up the web address in the hash table, and if it exists, goes to the LRU list entry, removes it and puts it at the top of the LRU list. If there is no entry, it adds one in the hash table and in the LRU list. Since this processing is done "off-line" at the end, it does not interfere with performance and enables good web page replacement decisions on the disk (see below).
This structure gets a good first response, with perhaps inconsistant data, but later corrects the data, so consistancy is compromised for performance. This structure also gives us fault tolerance. If the home of the page is down (and the fetch thus does not return a document), the web cacher still presents its cached page, if one exists. For failure detection, the web server would include a user option to notify or not when the remote server does not respond.
When the OS pages out a web page, the web cache stores the page on disk. If the page is new and the web cache limit has been reached on the disk, the web pages at the end of the LRU are deleted until there is enough disk space for this page, and then this page is stored. We keep some slack, so that if the page replaces a previous version of this page but is bigger, we can do so in most cases without deleting other pages. The OS then updates the hash and LRU lists.
Write back is faster in perceived user time because the user process does not wait for writes to hit the disk (this event happens later and asynchronously), whereas with write through every write goes to the disk and the process cannot proceed until the write completes.
Write through leads to more consistant and fault tolerant results because when the write completes, the process is assured the result is in permanent storage. With write back the process does not know when the write actually gets to permanent storage so it is harder for it to ensure both consistency and fault tolerance.
See above.
Write back is more complex because the OS must decide when to do the write (e.g., at certain intervals or when the file is closed) with write through, the OS simply does the I/O when the user requests it.
Yes the above solution still applies because the write through and back policies are the same on both systems, although on a distributed system the performance advantages of write back and the complexity disadvanges are exacerbated because of the additional layers.
class Game { public: RedCS(); GreenCS(), BlueCS(); private: Semaphore Red, Green, Blue; } Game::Game(){ Red.value = 1; // Red Semaphore is available Green.value = 0; // Green Semaphore is not available Blue.value = 0; // Blue Semaphore is not available for (i = 1 to numTeamMembers) { forkthread(RedCS); forkthread(GreenCS); forkthread(BlueCS); } } Game::RedCS() { Red.Wait(); ... red move ... Green.Signal(); } Game::GreenCS() { Green.Wait(); ... green move ... Blue.Signal(): } Game::BlueCS() { Blue.Wait(); ... blue move ... Red.Signal(): }