Sistemas Operativos - MIEEC
Project

1. Introduction

The goal of this project is to develop a device driver (DD) for the serial port. Although the 3rd and the 4th labs guide you through the implementation of a basic DD for the serial port, completing both labs will not be enough to achieve the maximum score. (Please check the annex for details regarding the grading criteria.) In order to get the maximum score you need to implement the enhancements described in this handout.

In the next section we discuss error handling, an issue that is so important that is in a section of its own. In Section 3 we present (other) operation-independent enhancements. Some issues related to testing these enhancements are presented Section 4. Finally, the handout terminates with a summary of the deliverables for this project.

2. Error Handling

Error handling is mostly independent of whether the DD uses polling or interrupts.

Error handling is difficult because it is device dependent. The rule, if there is any, is that the device driver should try to recover from any transient error, as long as it does not delay significantly the user process. Otherwise, it should report the error up to the application, which may better decide on the recovery action that is most appropriate for it.

The convention used is that a negative return value by a DD file operation indicates an error. The possible error values are those listed in the man page for errno. If the kernel functions used by the DD indicate an error, the DD can just forward that value to the user process. Otherwise, you need to choose the value that appears to best describe the detected error.

Another issue is that if an error occurs in a data transfer operation that partially succeeded, i.e. after transferring correctly some of the data, the operation should report success of the data transfer that actually occurred. The error has to be reported only in the following call of that operation. You can find a more detailed discussion of this issue Ch. 3 of the LDD3 book, pp. 65 (bottom) and following.

The weight of properly handling errors in the final grading is of 2.5%. Because it is hard to test this, you must include a section in your report (see Section 5) explaining how do you ensure the above behavior for the read() and write() file operations. Your explanation must include references to your code (including source code file name, and line numbers) so that we can follow it easily.

3. (Other) Improvements

The following is a list of some improvements to the seri DD that you have developed in the last class:

The percentage between parenthesis in each item is the respective weight in the final grade of your device driver. In the following paragraphs we give more details regarding each of these improvements.

3.1 Minimize global variables (2.5%)

It is likely that in the implementation of your DDs you did not pay much attention to the use of global variables. For example, in the implementation of the DD file operations you may use global variables rather than the arguments provided by the caller. Such an implementation works if the DD manages only one device, but it won't if it manages more than one device. Furthermore, there are several other reasons why avoiding global variables is the right thing to do when coding.

If you plan to do it right, don't wait any further. Clean up your code now, before it gets bigger. In principle, you should access data via global variables only in the module's initialization and termination functions.

3.2 Eliminate race conditions (2.5%)

In the previous labs on DD we have hardly mentioned the possibility of race conditions. The main exception was in Lab4 where we discussed the need for synchronization between the IH and user threads. In that lab, we have also mentioned in passing that a DD should ensure that, if concurrent threads make systems calls to access the same device simultaneously, they should synchronize to prevent race conditions.

Indeed, even if, as suggested in Section 3.6, you prevent more than one user, or even more than one process to access the same device, it is possible that multiple threads of the same process try to access the same device. Therefore, if your DD may leave kernel data structures in an inconsistent state because of race conditions, modify the code of your device driver to eliminate these race conditions.

3.3 Honor the O_NONBLOCK flag (2.5%)

The implementation of the read() and write() operations in your DD may lead the user process to block (or to busy wait, if the process yields the processor rather than sleep). This is the standard behavior of those operations.

By setting the O_NONBLOCK flag, usually on a file open operation, a process requests the kernel not to block on those operations. Therefore, if this flag is set, the operations should return immediately, without blocking or busy waiting, even if that means performing no I/O. For a detailed discussion of this issue you can check Ch. 6 of the LDD3 book, pp. 147 and following.

3.4 Add ioctl operations (2.5%)

The ioctl syscall allows to control a device by modifying associated parameters.

Your implementation of ioctl should allow to:

Indeed, configuring the communication parameters with hard-coded values in the module was a quick and dirty way of getting the UART configured so that you could communicate via the serial port. It would just not be acceptable in a production-level DD.

Given that usually one needs to set all serial communication parameters, you need only implement a single "set" command that allows to modify all the parameters. Furthermore, you should provide a "get" command that allows to read the current value of all the serial communication parameters.

You can check Ch. 6 of the LDD3 book, pp. 135 and following, for the details on implementing ioctl .

Note that if you do not use the serial port of the VM connected directly to the physical serial port of the host PC, all parameters, but the number of bits per character, are irrelevant. E.g., if you connect the serial ports of two VM it is irrelevant if you configure both serial ports to use the same bitrate, or a different bitrate: the outcome will be the same. (If you did everything else right, you'll be able to communicate via the serial port even though the bitrates used on two VMs do not match.)

3.5 Allow for interrupting a process inside a read() syscall (2.5%)

Depending on your current implementation of the read() syscall, a process may get stuck trying to receive data that will never arrive, and do not respond to any action of the user, even it (s)he types Ctrl-C.

If this is the case, you should change your device driver to allow a user to terminate an application inside a read() syscall.

3.6 Add access control to prevent more than one "user" to access the serial port (2.5%)

In principle, a serial port should not be used by more than one process, or at most by processes that belong to the same user.

The access control mechanisms of the Unix file system can limit access to only one user at a time, but not in a very straightforward fashion. It is easier for the device driver to perform the additional access control checks. The details for this are described Ch. 6 of the LDD3 book, pp. 173 and following.

3.7 Add FIFO support (2.5%)

The VirtualBox serial port emulates the 16550A, which is a UART that has two 16-byte FIFOs, one for transmission and the other for reception. These FIFOs are HW buffers, that allow for more efficient I/O.

By default, the UART does not use FIFOs. To use FIFO's you need to enable and configure them by writing to the UART's FIFO Control Register (FCR), which is a write only register. The operation of the UART with FIFO's is somewhat more complicated than without. You can find the details regarding its operation in pg. 19 of the data sheet of the 16550D UART from Texas Instruments, a more recent version of the 16550A.

Note that the UART's 2 FIFOs operate independently. Therefore, you may wish to add support to one of them first, and add support to the second one only after you get your DD working working properly with the first one.

2020 Update

The following enhancement has been cancelled. We cannot give you more than 20 points.

3.8 Add support for the select()/poll() system call (2.5%)

The select()/poll() system calls allow a process to wait for I/O on several "files" simultaneously. Furthermore, they allow the specification of a timeout value, after which they will return, even if no I/O has occurred. Therefore, even when performing I/O on a single file it may be convenient to use the select()/poll() system call to limit blocking time. You can find details on how to implement this in Ch. 6 of the LDD3 book, pp. 163 and following.

4. Test Programs

A challenging aspect of developing the enhancements listed in the previous section is testing them.

For each enhancement you implement, except the one in Sections 3.1 and 3.2, you must develop a test program that shows that the enhancement does what it is supposed to do. These test programs will be crucial in the demo of your project. Their code must also be submitted together with the source code of your device driver and will have a weight of 30% in the grade of the enhancements.

5. Deliverables

2020 Update

Because of CoViD-19, we are extending the deadline of this assignment to Tuesday, 2020-05-26, at 20:00 Saturday, 2020-05-30 at 23:59:59. However, to take advantage of this extension your group's remote demo will have to be schedled for the first days of June.

It is still possible for you to demo your project on your lab class, but in that case you'll have to submit your project until Monday, 2020-05-25, at 8:00.

By the deadline, you have to submit a zip archive according to these submission instructions. The zip archive must contain:

  1. A directory per DD: serp, for the DD that uses polling and seri, for the DD that uses interrupts. The files with source code should be named serp.c and seri.c, respectively. Each directory should also include a subdirectory, named test with the applications for testing the corresponding DD. You must also provide 1) the makefiles for generating the DDs and the test programs, and 2) the load and unload scripts for your DDs.
  2. A report (either a plain ASCII file or a PDF file) that should include:
    1. The state of development of your DD:
      • This need not be longer than one paragraph. You need only describe whether you have implemented a poll-based or an interrupt driven device driver, and which of the features of the relevant handouts you have implemented. For example:
      • We have implemented a poll-based device driver with all the features enumerated in Lab 3. Furthermore, we have implemented 3 of the enhancements described in Lab5: 1) it handles error's as described in Section 2 of Lab5; 2) it uses global variables only in the module's initialization and finalization functions (Section 3.1 of Lab 5) and 3) uses Linux kernel semaphores to prevent race conditions (Section 3.2 of Lab 5).
    2. For each enhancement mentioned in the previous item, a section:
      • describing the major design decisions, and relevant implementation details. In the case of the enhancements described in Sections 2, 3.1 and 3.2 you should include explanations including references to the source code, including file names and line numbers (as already described in Section 2.)
      • explaining how it was tested using any test program, which must be included in the corresponding directory. (As mentioned in Section 4, you need not submit the test programs for the enhancements described in Sections 3.1 and 3.2, neither for the enhancements described in Section 2.)

Remember that you must demonstrate your project in the lab class of the week starting on May 25.

Finally, you must also fill this Google form with your self-evaluation, until Tuesday 27th, at 22:00 (in the evening). Please note that this form must be filled by each group member. So that you can update your form, e.g. if you fill it in different sessions, you are required to login with a Google's world account. Remember that U.Porto subscribes the Google Education service and that every one with a UP account can create an account in that service, as explained here. If you fail to fill this form, you may be penalized, if your group mate and/or the lab staff have a different idea of your contribution to your project.

Annex: Grading Criteria

Your grade in the "DD project" will depend mostly on what you will demo: code that "almost works", whatever that means, will not get any credit. A serial port DD that "works" must be able to at least send/receive chars via the serial port, when a user program invokes a write/read system call on the respective device file.

We will also take a look at your report and at your source code, but roughly the ceiling of your grade depends on what you show that is working. The following is the table that we will use to determine the ceiling of your project's grade:

Grade Ceiling
DemoCeiling
Poll-based DD (DD Lab3)12
Interrupt-driven DD (DD Lab4) 15 16
Enhancements (this lab)20

Please take into account the following considerations: