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.
In the `MMailBox' class, when calling `sendmsg()' the process should check to see if the message being sent is addressed to a process in the `WaitQueue', and if so wake it up and stick it back in the run-queue. But how can this be done ? It seems horribly inefficient to call `get_from_queue', test the PID and either wake it or put it back with `add_to_queue' for all of the processes in the queue. Am I approaching this in the wrong way?
Actually, the approach you suggest would be mostly fine -- except that you can't guarentee that it will work. Although you can find out whether a particular process is waiting (by removing, testing PIDs, re-adding), you can't know (without adding extra things) whether or not the receiver is waiting for a message of the `type' send, or even a message from the process calling `sendmsg'.
This is a fairly low-turnover mailbox, so efficiency isn't critical. Best efficiency would be obtained by having per-process mailboxes, but I'm not expecting you to do that.
An alternative approach would be: put all the waiting processes back on the run-queue. When the receiving process wakes up, it can check for messages and if none, simply goes back to sleep again.
Referrers: Question 29 (2003)
``Generally speaking, the `type' can be any positive integer...''
Does this mean that, as a part of out defensive coding, we should ensure that the `type' is greater than or equal to -1?
If this is the case (or in case of erroneous fields being passed into any methods we define, in general), how would we go about han dling `bad' messages - are they simply discarded?
Yes, you should check the validity of `type' -- user-programs (the general programmer) might try all sorts of stuff!
Errors are reported through return value. In the case of, say, `sendmsg' for mailbox passing, a bad `type' (or other) field should result in the message being discarded/ignored and an error returned to the user (integer return). The value should be appropriate, e.g. ``-MSystem.EINVAL'' for a `bad value'. Error-constants and their codes are listed in the MSystem Javadoc.
Keywords: moss , return-values
In the assessment description you say that `sendmsg' should have the parameters `pid', `type' and `message'; and that `recvmsg' should have `pid' and `type'.
However, in the MOSS slides you say that `sendmsg' and `recvmsg' need source PID and destintion PID. Am I missing something here?
Not exactly -- when calling `MPosixIf.sendmsg()', the destination PID is given -- the source PID is simply the PID of the invoking process (i.e. the one calling `sendmsg'). And visa-versa with `MPosixIf.recvmsg()', except that the (source) PID argument may be -1, meaning to receive from any source.
Referrers: Question 25 (2006)
For the mailbox question, I am currently testing it using your testrig. However the output is slightly different. The difference is the fact that my outputs the ``UMailSend: done. exiting.'' in about the middle of the output rather than the end. I was just wondering if this is still correct. I thought it maybe as the sender has done its job to send the all of its messages and has nothing else to do. Or does this mean i have missed something out?
That's fine -- providing that `UMailRecv' receives the four test messages successfully.
Referrers: Question 57 (2003)
Blocked processes `vanishing' from a `MWaitQueue'.
Synopsis: There's a slight bug in MOSS's `MWaitQueue' class.. :-(. But that's the only bug I've found so far..
Fix: In `MWaitQueue.java' at line 69 is:
tail.q_next = p; p.q_next = null;
There is a line missing from this, those lines ought to be:
tail.q_next = p; tail = p; // this line p.q_next = null;
You should fix that in your own copies of MOSS. Alternatively download the fixed MWaitQueue.java.
I have a test program which writes data to a device-driver in the same way that `UPipeTest' creates and writes to a pipe, the only difference is that it creates a new child process to do the test so that I can still use the console while the test is running. However when I create 2 instances of my test they are given the same file descriptor, yet the tests still complete perfectly. How can this be ? Do I just not understand what a file descriptor is or is this a very strange bug ?
Note: My method for creating an instance of the device driver is more or less a copy of the method used to create pipes.
Firstly, file-descriptors are per-process. So, every process might have a different file open for the same descriptor. At the other end of the scale, many processes might have the same file open, but assigned to different descriptors.
Secondly, when a process creates another process (using `MPosixIf.forkexecc()'), any open files (identified to the process by an integer file-descriptor) are duplicated. This has the effect of increasing the `refcount' field inside the `MFile' structure/class for that file.
So, if you open your device driver, then create the other processes, those processes will automatically get a copy of the file-descriptors open in the original process. Both can use the file in the same way. In all likelihood, having your two test-programs run normally is fine. The underlying device is only `close()'d when the last reference to the file is `close()'d.
Keywords: moss , device-driver
With the `lseek()' method in `MPosixIf' is it ok if I change the error value to -1 as if you `lseek()' to an offset of zero it looks the same as when you get an error.
Seeking to an offset of zero is fine. Zero from the start is the start-of-file, zero from the end is the end-of-file. If whatever is being `lseek()'d is incapable of supporting it (streams, pipes, etc.), you should return an appropriate error. -1 is not an appropriate error. ``-MSystem.ESPIPE'' (illegal seek) might be more suitable.
Keywords: moss , return-values
For question (1b) (mailbox), do the `pid' and `type' of the `sendmsg()' method have to be more than or equal to 0 and not allowed to be less than 0? And also for the `recvmsg' method the `type' and `pid' cannot be anything less than -1. is this correct?
Yes, that's correct.
For the mail box, where are we expected to send the processes to in the `sendMessage' method?
As I understand it:
Your question makes little sense -- you can't `send' a process anywhere. Maybe one day, when MOSS supports process migration between machines, we could.
If you're referring to the handling of blocked processes, then your `sendMessage' should reschedule blocked processes by placing them on the run-queue.
See also the answers to Question 7 (2003) and Question 21 (2003).
I've decided to do the mailbox system and I am just trying to understand it.
So if a process wanted to send a messsage would it create a mailbox call the `sendmsg' method and put it in the collection inside `mailbox' and the other process would then run `recvmsg' on the `mailbox' and get the message.
The idea is correct, except for the `creating a mailbox' bit. There is no mechanism to do this from the user-process perspective -- it can either send a message, or receive a message. There is no facility for mailbox `management'. That's what the user process's will do (see the test-programs for mailboxes, downloadable from the MOSS page).
I was testing the mailbox question and I flooded MOSS with the `run UMailRecv' command to see how it would react (and being bored at the time). It works for a while then I get a silly error. This occurs only after the process has finished. I think must have flooded it with about 20 of the `run UMailRecv' commands. Also sometimes it says unrecognised command before hand with ramdom rubbish as the command.
MOSS# java.lang.ArrayIndexOutOfBoundsException at java.lang.System.arraycopy(Native Method) at MJavaConsole.read(MJavaConsole.java:246) at MPosixIf.read(MPosixIf.java:188) at UConsole.main(UConsole.java:67) at MProcess.run(MProcess.java:252)
This sounds like a small bug with the keyboard input handling (I assume you're running on a Sun JVM, e.g., on Solaris or Linux). I'll look into it, but it won't be fixed for this assignment. Thanks for pointing it out, though.
How do i add a message (of `Object' type) to the `MMail' box ? I was thinking to do as follows:
MailMessage mess = new MailMessage(pid_from, pid, type, message); box.addMail(mess);
But obviously the `MPosixIf' class doesn't know what the `MailMessage' class is since it is declared as a private class of `MMailBox'.
The code fragment you've given should actually be inside the `MMailBox' class, where `MailMessage' is visible. The rationale is that adding messages to a mailbox is something that the mail-box implementation should do; not the user-kernel interface (MPosixIf). More specifically, what a mail-message is should be private to the mail-box implementation; so any code that uses it directly should be in the mail-box implementation too.
In response to an answer further down the page.. For the mailbox (1b), how do I get/find out the PID of the invoking process ? I have no idea how to go about doing this. Cheers
See the answer to Question 10 (2003).
Keywords: moss , process-id
Hi,
I'm finding this assessment incredibly difficult. I've been to the extra lecture on MOSS and most of the CO501 lectures and read all the anonymous questions. However, I can't even begin to make a start on it really. I'm trying to decide which option I want to do (between the first 3, because they are 'guided') but I can't because I don't think I have sufficient java knowledge to do any of them. I'm not quite sure what this has to do with the Java programming skills we have been taught because everyone seems to have trouble with using these static methods instead of objects and so on, and that's not the way we were taught Java. It seems to me that this assessment assumes that people have a level of Java which is far greater than that which we have been taught. Which is probably the case for some CS2 students but not for myself and I think/hope others as well. I'm really having a hard time even getting anywhere with this.
I'd agree with your point about this being fairly `hard' Java. Static methods should not be hard to understand, however; particularly given that you've now learnt a bit about C (which has no concept of `objects'). Even though you may not have been taught explicitly about static methods (and non-object-oriented programming), it's something that you should be able to read up on for yourself.
As a quick example, the Java code:
public class Thing { private static int x; public static void foo (int v) { x = v; } public static int bar () { return x; } }
Is equivalent (more or less) to the C code:
static int Thing_x; // "static" effectively means "private" in C void Thing_foo (int v) { Thing_x = v; } int Thing_bar (void) { return Thing_x; }
So, in C, when you write ``Thing_foo(42)'', the equivalent in `static Java' would be ``Thing.foo(42)''.
I'm more than happy to explain the nature of `static' in more detail, through any of the communication means (anon q+a, email, in-person). The first (anon q+a) will produce faster responses, however, since these are read by many.
As a side point, C would be a much better language for MOSS; largely because it avoids the OO-related confusion. You only know Java (in imperative langauges), however.
Keywords: moss
Referrers: Question 76 (2003)
Sorry, in follow up to the last question/complaint.
Couldn't you at least provide an easy option (you said the first 3 were the `easy' options but I really don't find that), like David Barnes did in the first year Java, so that people that aren't Java gurus will have at least a chance at getting maybe at least 50% on this assessment since it's worth 10% of our overall grade? I'd really like to give it a shot but I don't think I will be able to get too far as it stands because I am very confused.
The two `easy' (and I use that term vaguely) options are (1b) and (3). The mail-box kernel implementation requires programming in the internals of MOSS. The demonstrator program(s) option does not, however, and as such should be generally `simpler' (less complex).
I must admit I did not even think about providing a specific `easy' (for less marks) option. In hindsight this might have been a wise idea, but the virtue of such assignments remains debatable (in my opinion).
The last 8 or so slides from the extra MOSS lecture were designed to help people get started with the assignment. Getting going on option (1b) is harder than option (3) -- for option (3) you can start by simply copying one of the existing `U...' user-programs and going from there. Option (1b) requires a reasonable amount of fresh code before things can be compiled, etc.
Whatever option you choose, marks will be allocated in a `linear' fashion, following the 4 general marking points from the assignment description. If, for example, you chose option (1b), but your implementation doesn't work properly (or at all), you can still get marks. If you know what you want to program, but can't express it in code, express it in comments (pseudo-code if you like). That will be worth more marks than nothing at all. This applies to most of the options equally, except (3), where the value of real-code is `higher' (since the general complexity of the code will be `lower').
Keywords: moss
Referrers: Question 76 (2003)
Is it appropriate to use iterators to go through the `ArrayList' of messages for (1b), or would you prefer us to stick to a basic loop (`for()' or `while()'), possibly because simple loops are more likely to be a structure supported at the lower levels in MOSS ?
I'd prefer a `for()' (or `while()') loop, but using an `Iterator' is fine, assuming it doesn't lead to extra complexity. For example, if you're scanning an `ArrayList' with the intention of removing an item once found, a `for()' loop is probably more suitable -- since you need the `index' to remove an item, and an `Iterator' doesn't give you this. Sure, you could use the `remove()' method on the `Iterator', but to me:
things.remove (i);
is more meaningful than:
it.remove ();
Keywords: moss
In response to your reply for Question 10 (2003), would you prefer the solution to be more time-efficient at the cost of space-efficiency, or the other way around. My guess would be that time would be most critical because an array of `ArrayList's wouldn't take up that much space - but I don't know quite enough that I feel confident making the judgement call myself.
As far as efficiency goes, a (sensibly) indexed array of `ArrayList's would indeed be better than one single big `ArrayList'. Time/space efficiency is often a trade-off. In this case, the increase in time-efficiency would more than compensate for the loss in space-efficiency (well, we'd certainly hope that is the case).
As a general rule, though, Java is not efficient (when compared to real languages such as C or occam). Too much in Java is outside the control of the programmer -- e.g. we don't know how an array, or an `ArrayList', is implemented. That means we can't judge its efficiency easily, and it may vary between JVM implementations.
Scanning through one big `ArrayList' would typically give O(n) time and space complexity. Indexing an array to get the `ArrayList', that is then scanned, would typically give O(m) time and O(n) space complexity, where ``m = n / array.length'' (i.e. if the array is small, the increase in time efficiency will also be small; if the array is big (and well-populated), the increase in time efficiency will be large).
Keywords: moss , efficiency
For the `MMailBox' should I put the call to get the current process ID in the `MMailBox' class itself, or should I put it in the methods in `MPosixIf' and then pass it on as a parameter.
It's just that I have a feeling it will be more secure calling it from the `MMailBox' class because it could reduce the scope for interference from rogue O/S components (i.e. processes stealing other processes' messages by passing the wrong pid to `MMailBox').
Extracting the current PID in `MPosixIf' and passing it as a parameter to the method in `MMailBox' would be the preferred method. That way, the method in `MMailBox' is `complete' -- all the information it needs internally is given explicitly (well, mostly, putting a process to sleep requires a bit more..).
Your point about inteference is well-thought, however. But, given the fact that only the operating system internals should call `MMailBox's methods, means we shouldn't have to worry about rogue componenets. In fact, by passing the `invoking' PID as a parameter means other processes could `snoop' on messages (i.e. by pretending to be a different process) -- this is something that we might want to support in the future (but not at the moment).
Your marking criteria has presented me with a few questions:
Thanks for setting up this page. It's been a real godsend.
Oh, and its just an observation but all your question references refer to 2003.. should these not be 2004 ? :-)
A switch should be used when you're selecting based on the value of something -- and there are a significant number of them (more than 2). For example, if a class contained something like:
class Test { public static final int ZERO = 0; public static final int ONE = 1; public static final int TWO = 2; ... }
Then a selection based on those values would be better done using a `switch'. e.g.:
switch (x) { case Test.ZERO: do_zero (); break; case Test.ONE: do_one (); break; case Test.TWO: do_two (); break; default: do_default (); break; }
Using an `if' for such a selection would be `ugly' (and gradually gets less efficient as the number of cases increases -- a `switch()' is typically O(1), stacked `if's around O(n)):
if (x == Test.ZERO) { do_zero (); } else if (x == Test.ONE) { do_one (); } else if (x == Test.TWO) { do_two (); } else { do_default (); }
As far as checking parameter sanity goes, the (ideal) theory is this:
So in effect, yes, check parameters for methods in `MPosixIf' (since this is where user-applications enter the MOSS `kernel'); and yes, you don't need to make these checks again in `MMailBox' (since these methods are only ever called from another part of the kernel -- probably `MPosixIf'). Some other bits of MOSS (outside `MPosixIf') do check their parameters, but usually these are because the effect of a bad parameter would be fatal (null-pointer exception, deadlock, etc.).
The 2003 refers to the 2003/2004 academic year :-) (less confusion for the years either side..).
How do we run the `UPipeTest2' test ? What parameters are needed ?
You don't! `UPipeTest2' is started automatically by `UPipeTest'.
The parameter is the file-descriptor that `UPipeTest2' will use to read data from the pipe. However, this is only present when it was started by `UPipeTest' (where the pipe is created, and new processes inherit the open files of their parent).
Maintained by Fred Barnes, last modified Thu May 8 12:58:05 2014 |