CO527 Anonymous Questions and Answers |
This page lists the various questions and answers. To submit a question, use the anonymous questions page. You may find the keyword index and/or top-level index useful for locating past questions and answers.
We have taken the liberty of making some minor typographical corrections to some of the questions as originally put. Although most of the questions here will have been submitted anonymously, this page also serves to answer some questions of general interest to those on the course.
Testing 1-2-3
Check
For question 1 of the assesment, do we have to do parts a, b and c? or do we just need to do 1?
Just one. I.e., either (a), (b), xor (c).
Hi, I'm thinking of writing a virtual printer driver for MOSS. I just wanted to know where I would initialize something like a print spooler, would it be in `MPosixIf or `MSystem' ?
Since you have to create an instance of XXX to allow it to implement `MFileOps', local initialisation should be done in `XXX.java'. For creating the thing in the first place, add a static method to MPosixIf. (Note: this is not an ideal situation, but MOSS currently lacks the generic support for this sort of thing).
Keywords: moss , device-driver
I've been reading the moss slides and I'm still having problems getting started on the assessment. I've been trying `1a' which seems to be the same as `MPipe' but with modified `read/write' methods. But I'm not sure how to detect the end of file condition or `SIGPIPE'.
The sheet says to generate `SIGPIPE' when a process isn't ignoring the signal. Does this mean generate `SIGPIPE' when a process is not sleeping ?
Also, looking at the `MPipe' `read(...)' method, I'm not sure what the values mean. I assume:
however when doing the `arraycopy' you read from the tail, shouldn't it be from the head?
An end-of-file (for a reader) occurs when the writing process `close()'s the pipe. The reader must empty the pipe of data first (if there is any), however. When a process exits, any files it had open are automatically closed -- assuming that the exiting process was the only one using that file (reference-count in `MFile').
The writer doesn't get end-of-file when the reading process `close()'s the pipe -- it's not really meaningful for an output-only stream. Instead, when the writer writes, it gets signalled with SIGPIPE (assuming it wasn't ignoring the signal). The underlying `write()' should return the appropriate error in such a case: `MSystem.EPIPE'.
In response to your second paragraph, nope. Inside `MProcess', there is a `signal-handling' array, indicating how the process handles each signal. You don't really need to worry about this too much -- look at the code for `queue_signal()' in `MKernel.java' -- that takes care of not delivering an ignored signal and also the resuming of sleeping processes.
For buffer management, it depends on how you look at it. The way I work these things generally is:
If we choose option 1 for the MOSS assignment, we have to do both sub-options A, B, and C, right?
Nope, only one! -- see the ``five options'' in the slides, they relate to (1a), (1b), (1c), (2) and (3).
Having a few problems with starting the assignment. I have chosen the mailbox option and did attend the extra lecture but have a few problems/questions...
The exact code in the slides:
private static class MailMessage { public int from pid; // source public int to pid; // target public int type; // type public Object msg; // message }
This gives me an error `'modifier statement static'' not allowed here.
Why should all of the methods and attributes in `MMailBox' be static rather than just public or private ?
Do I need to relate the new class `MMailBox' to `MPosixIf' by some means such as `implements' or `import' ? Or am I supposed to create an instance of `MMailBox' instead?
I am thinking the second way is correct but I was quite confused by this part of the assignment doc:
This will require adding two methods to the 'MPosixIf' class, to provide the user-interface. I'd like this interface (in MPosixIf) to be:
public static int sendmsg (int pid, int type, Object message); public static Object recvmsg (int pid, int type);
Am I supposed to leave the above methods as `empty' and implement them in `MMailBox' ? Or are they just method headers that need a body in `MPosixIf' ?
Is there going to be an anon question page ?
This isn't quite verbatim; there should be under-scores in `from_pid' and `to_pid'.
The `MailMessage' class is intended to reside inside your `MMailBox' class (i.e. inner-class); since it's very private to that class. If you try and put it in a separate file, or at the top-level, `javac' will complain -- unless you remove the `static' modifier, of course.
Because `MMailBox' isn't an `object', therefore we don't want to be creating instances of it. You can only call non-static methods on an object, not on the class. Hence, most things are `static', and called with:
MPosixIf.close(...)
for example, rather than having an instance of `MPosixIf' on which methods are called.
None of these. The code you add to `MPosixIf' should simply do:
MMailBox.sendmsg (...)
for example. What you describe are object-oriented concepts. We don't necessarily want OO here, but Java is the only suitable language in this case. A C version of MOSS would not be entirely different (logic wise), but would be much harder to program -- Java is quite helpful when it comes to run-time errors.
As for the `sendmsg/recvmsg' headers give, yes, they are headers that need method bodies inside `MPosixIf.java'. Such methods should do like the others in `MPosixIf': check parameter sanity, etc., then call the specific method (e.g. `MMailBox.sendmsg()').
Good idea. Hopefully :-).
Referrers: Question 39 (2003)
I'm looking at doing the mailbox question on this assignment and have a few questions.
Is a mailbox used between just 2 processes or can this be more ? Is a common shared mailbox used or a mailbox for each process ?
I get that the mailbox is a form of communication between processes but what kinda of data do they pass between them?
Am I right in thinking that I should add methods in `MPosixIf' to use this mailbox feature?
So the mailbox is used to store messages but why wouldn't the processes just receive them straight away or do processes randomly check this mailbox ?
It depends on how you look at it (and/or implement it). From the point-of-view of a user-process, a message is something sent from it to another process, or something received from another process, involving just two processes (sending and receiving).
There are essentially two ways of implementing this:
The second method is the simplest, although the first would be equally valid.
That's up to the application. The `MPosixIf' methods to be added have the message as an `(int, Object)' pair (type and message). How the application uses this is entirely up to it. The sending and receiving processes must `agree' in advance how they're going to use the `type' and `message'. One pair of applications might use `type' 0 to mean `the message is a String', and `type' 1 to mean `the message is an array of Strings'. Other applications might use different conventions -- it's up to them; MOSS merely provides the communication facility.
Analogy: the Royal-Mail: your job is to take messages and deliver them to their destinations (where customers `recvmsg()' their mail..!). What the message `contains' is irrelevant to you; it only has meaning to the sender and receiver.
Your implementation should be in two main places
There is no way for a process to asynchronously receive a message (well, you could do it by adding a signal, SIGMAIL, but that's not what's wanted here..). The only way a process can receive a message is by explicitly asking for one (by calling `MPosixIf.recvmsg(...)', that you have to implement). If no messages are available, the receiving process should block (i.e. wait for a message).
When a message is sent, the `MMailBox' sendmsg() (or whatever you wish to call it) will have to check to see if the receiving process was blocked (waiting for a message), and if so, wake it up. There are various ways you can handle this..
Referrers: Question 11 (2003) , Question 29 (2003)
Basically in `MPipe.java' what is `bufIn' ? I just cant figure out what its meant to represent! Its probably really obvious, but I need to know before I carry on going through the class.
It's the number of bytes in the buffer. The value could be worked out from the others (e.g. `(bufsize - bufleft)'), but it's easier to have it as its own variable (improves patency (`obviousness') of the code, and thus readability).
I think I have a better understanding of what needs to be done. However, how do I tell if it is a reader or writer calling the `close()' method in `MPosixIf' ? Is it possible to determine this from the current `MProcess' ?
Looking at the `pipe()' method, `fds[0]' is for reading and `fds[1]' for writing, but as these are local parameters; I can't use them in `close()'.
Also for the end-of-file condition is it ok to use any negative number ?
In response to your first point, not entirely..
In the existing `MPipe()' implementation, a single `MFile' is used for both the reading and writing descriptors. In order to tell the difference inside your pipe implementation, you'll need two different `MFile's, one for the reading process and one for the writing process (initialised in a similar way, however). Thie, of course, means saving that information somewhere inside the pipe when it is created (so that `close()' can find out which end is being closed).
In the existing pipe implementation, `MPosixIf.pipe()' returns two descriptors that refer to the same underlying `MFile' (given a reference-count of 2). When the first of these two descriptors is `close()'d, the reference-count is simply decremented (to 1). Only when the second descriptor is closed will the underlying `MPipe.close()' method be called.
For an implementation that needs to tell the difference, you must use two `MFile's, so that when either one is `close()'d, the underlying `close()' method will also be called.
For your last question, from the MOSS Javadoc for `MFileOps's `read()':
Returns: number of bytes read, 0 on end-of-file or < 0 indicating error
I've chosen option (1b), and I am trying to decide whether to use an `ArrayList' or `HashMap. But to decide that, I need to understand what the `type' field is used for. It seems to me that to receive a message, both the process ID, and the `type' need to be specified?
In that case a `HashMap' won't work. Also I don't understand what you mean when you say that `type' is ``application specific'', and how we find out which process sent a message (needed to give `MailMessage.from_pid' a value).
An `ArrayList' would be my preferred `container'. Not sure that a `HashMap' would be quite right -- efficiency isn't a key issue here, as long as it's no worse than O(n) (e.g. `for()' loops, etc., rather than hashing which gives more like O(n log2 n) -- assuming you know what big-O is..).
A very (time) efficient solution could be made by creating an array of `ArrayList's of mail-messages, with the top-level array indexed by destination PID. This is not particularly space efficient, however, and could make the code somewhat complex.
For a receiving process, the `type' and `pid' parameters are `optional'. A process can receive a message from a specific source (the `pid' parameter) or any source (`pid' == -1), and additionally receive a message with a specific `type' or any `type' (== -1).
For example, one user-process might do:
Object message = MPosixIf.recvmsg (-1, -1);
meaning `get any message sent to me'. That would work with a sending process like:
String message = new String ("Hello, mailbox world!"); MPosixIf.sendmsg (otherpid, 0, (Object)message);
where `otherpid' is the PID of the receiving process.
``Application specific'' is exactly that -- the kernel implementation mostly doesn't care what the actual value of `type' or `message' are, it just communicates those things. The only involvement is the checking of `type' when receiving (and applications should only use 0 or +ve `type' values..).
The PID of the current process can be extracted through its `MProcess' structure. For example:
MProcess current = MKernel.current[MProcessor.currentCPU()]; // current pid is "current.pid"
Referrers: Question 33 (2003) , Question 37 (2003) , Question 42 (2003) , Question 63 (2003)
I must admit that I'm a bit confused about what exactly we are meant to be storing in the `ArrayList' for the mailbox implementation. In the MOSS lecture notes it states you should ``maintain an ArrayList...of `MailMessage' objects''. However, in these notes, `MailMessage' is a static class, and I thought you could not create instances of a static class let alone be able to store them in an `ArrayList'? I also get the impression that processes need to be able to create new mailboxes, rather than just being able to store `MailMessages', though I'm not sure if that's an entirely different question.
The reason for a static class here is somewhat fuzzy. In my own mind, I'm not sure `static' means anything when used in a class definition. However, if you try and reference an inner-class from a static method, that inner-class must be declared as static -- or `javac' produces an error:
ITest.java:11: non-static variable this cannot be referenced from a static context Inner i = new Inner (); ^
By the looks of it, it's an error about the lack of a `this' inside the static method -- which would be correct. Exactly why it needs the current object reference to create a new (inner-class) object, I'm not sure.
In response to your last point, see the answer to Question 7 (2003). Mailboxes, in this case, are identified by process ID (to whom the message is sent); thus every process gets an implicit mailbox.
Referrers: Question 62 (2003)
I'm trying to implement the `MMailBox' class and I would like to clarify a few things:
Am I right in thinking that the `MMailBox's `sendmsg' method simply puts the message in an `ArrayList' and waits for the right process to recieve it ? In which case how are we to index the array list, as we would need to know the `from_pid', the `to_pid' and the `type' to recieve the right message(s) ? This seems like it would be quite complex and I don't think its quite what you had in mind.
Any clarification appreciated.
You're mostly right in your first question -- `sendmsg' simply puts the message in the `message-store', but it does not need to wait for the other process to receive it. `recvmsg', however, should wait, if no messages are available. (this is a `regular' mail service, ``recorded delivery'' -- a blocking `sendmsg' -- is not needed).
You're right in thinking that indexing the array can't be done simply, given the combination of fields required. However, array indexing here does not need to be done `intelligently'. Using a `LinkedList' instead of an `ArrayList' is a possibility -- both have their relative merits. To see if a message is available in `recvmsg', scanning the array/list would be sufficient.
So according to your answer to the previous questions the `mailMessage' class still creates instances of `MailMessage' despite being static.
I'm still getting the non-static referencing error, and can't work out why ?
private static class MailMessage { public int from_pid; // source ... }
Where do we get the `from_pid' and the `to_pid' ?
The messages that we return from the `ArrayList' when the `recvMsg' method is called are returned on a FIFO basis?
Works fine for me.. Remember, such `private static' classes only make any sense when inside another class. Also, I don't think you mean `mailMessage' (1st occurence). E.g.:
public class MMailBox { private static class MailMessage { public int from_pid; // source ... } // ..static variables and static methods.. }
Where the `from_pid' and `to_pid' come from depends on whether it is `sendmsg()' or `recvmsg()' being called. For `sendmsg()', `from_pid' is the PID of the invoking process and `to_pid' is provided as a parameter. For `recvmsg()', `from_pid' is provided as a parameter (or -1 meaning receive from any process) and `to_pid' is the PID of the invoking process.
FIFO behaviour isn't strictly required (nor guaranteed) -- messages between two processes may not be received in the order sent, depending on how the receiving process selects them (specific source and/or specific type vs. any).
Am I right in thinking that we are going to have to have some pretty complex code for the `MMailBox' class to prevent concurrent storing and retrieving of messages, as well as the code to stop concurrent retrieving of messages.
You right in the sense that you need something to prevent concurrent access, but it's not that complex.. Basically, you need to ensure that access to the shared `message pool' is mutually exclusive. The Java `synchronized' block can do this. E.g.:
synchronized (message_pool) { // manipulate message_pool }
This gets slightly messier when combined with process scheduling, however, as a process must not deschedule whilst inside a `synchronized' block (otherwise no other process will be able to enter a `synchronized' block on that object).
As mentioned in the assignment description, some of the marks awarded will be for the correct handling of concurrency.
Keywords: moss , concurrency
I'm confused about (1c) ... you mention a static `Sema4' class in the MOSS notes and I'm not sure where that comes into the assignment. Also I don't understand what the `op' int is for ... again me being stupid and confused I'm not quite sure what the `semop' method in the `MPosixIf' class is meant to do.
The `Sema4' class is intended to hold information about a single semaphore. These are managed centrally by another class (`MSemaphore', for instance).
The `op' parameter is operation. As explained in the description, this is either `SEMOP_CREATE' or `SEMOP_SET', that create and change a semaphore value respectively. These semaphores do not have explicit `wait()' and `signal()' methods, but in effect:
the `_CREATE' and `_SET' constants will be defined in your `MSemaphore' class (so technically it should be `MSemaphore.SEMOP_SET', etc.).
The `semop' method (in `MPosixIf') is the user-process interface for performing semaphore operations. This should perform suitable checks, etc. then make an appropriate call to a static method in your `MSemaphore' class. For example, a fragment from a user-process might be:
MPosixIf.semop (MSemaphore.SEMOP_CREATE, 100, 0); // create semaphore with initial value 0 MPosixIf.semop (MSemaphore.SEMOP_SET, 100, 10); // up semaphore value by 10 MPosixIf.semop (MSemaphore.SEMOP_SET, 100, -11); // down semaphore value by 11 (will block)
Such a user-process should not terminate, unless another process comes along and `up's the semaphore value by 1.
Referrers: Question 43 (2003)
When implementing the `MMailBox' do we store blocked processes on a static `MWaitQueue' in the `MMailBox' or in the `MPosixIf' class?
The former would be preferred -- blocking using a static `MWaitQueue' inside `MMailBox'.
Keywords: moss
What `int' is this returning?
public static int sendmsg (int pid, int type, Object message)
The integer returned should indicate the result. The convention should be mostly obvious from the other `MPosixIf' methods:
Keywords: moss , mailbox , return-values
Referrers: Question 47 (2003)
Can you specify what methods we should use to make a class `wait' or to `start' a class back up as we cannot use `wait()' and `notify()' and can you explain how these methods work?
An overview of how this is done was given in the extra MOSS slides (downloadable from the course web-page (under lecture-notes). A real example of how it's done can be found in the `MPipe' class provided.
But essentially, to put the `current' process to sleep:
MProcess current = MKernel.current[MProcessor.currentCPU()]; // set state to sleeping current.state = MProcess.TASK_SLEEPING; // add to wait queue wait_queue.add_to_queue (current); // reschedule MKernel.schedule (); // when we get here, the process has woken up again if (current.signalled) { wait_queue.del_from_queue (current); // abort and return with EINTR (interrupted) }
To wake a process up again (which can only be done in the context of a different process):
MProcess other; // get process from queue other = wait_queue.get_from_queue (); // add it to the run-queue for scheduling MKernel.add_to_run_queue (other);
Referrers: Question 51 (2003) , Question 59 (2003) , Question 61 (2003) , Question 66 (2003) , Question 69 (2003) , Question 69 (2003) , Question 73 (2003) , Question 74 (2003) , Question 74 (2003) , Question 77 (2003) , Question 79 (2003) , Question 87 (2003)
For the `Pipe' you said that you needed to store the infomation about the two file handles (`MFile's) inside the pipe object somewhere, so we could tell whether it is being closed by the reader or the writer. If you simply store a copy of the `MFile' objects when the open method in pipe is called, when you come to close, the pipe fields (i.e. the `refcount') would have been changed so you cant compare the two (the one you have stored and the one being handed as a parameter when closing the pipe). So how do you suggest getting around that?
I'm not sure I understand your question.. If you have a two `MFile' references inside your pipe implementation (one for reading, one for writing), the `close()' method (on the pipe) will always be called with one of these as an argument. This is the same object reference, so just do reference comparison, e.g. ``if (fh == reader_handle) { ... }''. That can't be the same as the other (e.g. ``writer_handle'').
On (1c) when trying to implement the `Sema4' static class so far the only way I've managed to make the code compile is by doing the below but I'm not really sure if it's right.
public MSemaphore(int o, int k, int v) { .... }
Am I heading in the right direction?
This isn't really what I had in mind for this. The semaphore `objects' are represented by the local `Sema4' class, held in a suitable container within `MSemaphore'. As a guide, I would expect all the methods and attributes/fields in `MSemaphore' to be static. You shouldn't create instances of `MSemaphore', only instances of `Sema4'.
Your `MSemaphore' class will probably need some initialisation, however. This can either be done explicitly by setting the fields, or programmed, using a suitable static method. E.g.:
public static void init_semaphore () { // code to initialise private state of MSemaphore }
Such an initialisation routine should be called from `MKernel.init_kernel()' -- thus add your `MSemaphore.init_semaphore()' call there (if this is how you want to initialise it).
Referrers: Question 43 (2003)
Maintained by Fred Barnes, last modified Thu May 8 12:58:05 2014 |