Advanced Operating Systems
COMP9242 2016/S2 |
UNSW
CRICOS Provider Number: 00098G |
Printer-Friendly
Version
|
M4: System call interface
The aim of this milestone is to design
the RPC
protocol for the system call interface. You should implement
both the client and system side of this interface. This
client-side system-call interface must conform to the interface
provided in musl libc and sos
For example, the shell does not call Not all syscalls have been implemented through musl libc as in
some cases the POSIX semantics are unnecessarily complex. You are
free to implement more of the functionality in any of the syscalls
defined in At this stage you will not actually be able to implement most
of the SOS (server-side) system calls, however you should be able to partially
implement
You should also change the implementation of Other system calls defined in Console deviceWhen a program opens the file Reading the console is a blocking operation. If a process reads from the console and there is no data available it should block until data becomes available. Be careful not to implement the console device as a 'hack'. You should think about being able to support multiple serial ports and other stream devices in your design (although not necessarily implement them). This means designing a consistent interface for interacting with all devices. You may want to read up on how Linux treats devices. You may once again find the documentation on libserial handy. Getting started
You will need to modify the libsos library to add implementations
of the interface defined in
You will also need to add sosh to the cpio archive that is linked
to SOS and instruct SOS to run this application. Both of these tasks
are achieved through the configuration menu. Run
Design alternativesAt this stage of the project you will need to decide whether you want to have a simple single-threaded server, or to multi-thread it. A multi-threaded design could be advantageous to deal with the inherent concurrency your system will have (e.g. between paging, system calls, asynchronous I/O and clock interrupts), but it will require careful design of synchronisation in order to avoid race conditions and deadlocks. A single threaded model will require extra attention to ensure liveness. Another design decision is how to transfer data between the kernel and user processes. Some options you have are:
Whatever you do, remember the basic engineering rule: keep it simple, stupid! (KISS). AdviceThis milestone is larger than it seems. The system call interface of an OS determines how user applications receive data they request. You will need to consider how you can move data in various quantities between your root server and clients. Scenarios to consider include:
Recall how OS/161 used an internal framework for safely transporting data between the OS and the application. The OS avoided simply reaching into application address spaces based on app-supplied pointers. You'll need to think about a framework (or at least a convention within your code) that can provide SOS with safe access to application memory. In later milestones, your approach will have to evolve to function in the presence in paging to disk, including paging application buffers. Recall also that the OS can't rely on applications for correctness. Any system call you add should behave gracefully in the presence of a malicious application - i.e. use error checking on system call arguments, and returns errors when encoutering problems. AssessmentDemonstrationFor this assessment you should be able to demonstrate
You should also show some sos application-level test code that
uses the
Demonstrate your The code below is the minimum demo to pass the milestone. Note that this code is not comprehensive, for best chances in the final marking you should test your sos_ interface extensively (edge and error cases). #define SMALL_BUF_SZ 2 char test_str[] = "Basic test string for read/write"; char small_buf[SMALL_BUF_SZ]; int test_buffers(int console_fd) { /* test a small string from the code segment */ int result = sos_sys_write(console_fd, test_str, strlen(test_str)); assert(result == strlen(test_str)); /* test reading to a small buffer */ result = sos_sys_read(console_fd, small_buf, SMALL_BUF_SZ); /* make sure you type in at least SMALL_BUF_SZ */ assert(result == SMALL_BUF_SZ); /* test a reading into a large on-stack buffer */ char stack_buf[BUF_SIZ]; /* for this test you'll need to paste a lot of data into the console, without newlines */ result = sos_sys_read(console_fd, &stack_buf, BUF_SIZ); assert(result == BUF_SIZ); result = sos_sys_write(console_fd, &stack_buf, BUF_SIZ); assert(result == BUF_SIZ); /* this call to malloc should trigger an sbrk */ char *heap_buf = malloc(BUF_SIZ); assert(heap_buf != NULL); /* for this test you'll need to paste a lot of data into the console, without newlines */ result = sos_sys_read(console_fd, &heap_buf, BUF_SIZ); assert(result == BUF_SIZ); result = sos_sys_write(console_fd, &heap_buf, BUF_SIZ); assert(result == BUF_SIZ); /* try sleeping */ for (int i = 0; i < 5; i++) { time_t prev_seconds = time(NULL); second_sleep(1); time_t next_seconds = time(NULL); assert(next_seconds > prev_seconds); printf("Tick\n"); } } As always, you should be able to explain both the design and your implementation. Show Stoppers
Better Solutions
Last modified: 13 Sep 2016. |