学习如何将 Linux Device 作为文件进行处理。
Requirement
The main objective of this lab will be to learn how to UNIX handles devices as
files. For the sake of this lab, whenever we refer to a file that is a device,
we say special file. Otherwise, it is a normal file like an image file or
program file.
Step 1. UNIX Devices as Special Files
UNIX’s kernel at its high-level of File System (File Manager) defines file as
an abstract entity to read from or write to. File could be part of a hard disk
drive that stores your C program main.c, another part of the hard disk drive
that stores your program executable main, or the whole hard disk drive. UNIX’s
kernel at its File System assumes all other hardware devices are also files.
The differences between the devices are handled by another part of the kernel,
Device Manager. So, like your files in your home directory, devices are also
files at /dev directory.
As seen, we have cpu (processor) and mem (memory), which are the two essential
parts of any computer system.
School’s computer system is a multiprocessor system; that is, it has multiple
cpus. So, you can go inside the /dev/cpu
and see how many cpus exist:
Let’s go into the first cpu.
Amazingly, devices are managed like files and directories that are directly
connected to the devices. You may be tempted to open them as normal files
using vi:
You see that vi is not able to read from cpu/0/cpuid like a normal file. Let’s
try it for memory device.
Is this because devices are not files and what we say is incorrect, or vi
program is not able to read from these special files? We’ll answer this
shortly.
What are other files? What is the file for mouse, keyboard, monitor, sound,
mic, hard disk drives, etc?
Important parts of a computer system are storage devices. Depending on the
type of storage, the file name for the device is either start with hd or sd
followed by a letter that distinguishes multiple hard disk storages. For
instance, sda is the first hard disk, sdb is the second, and so on. Also, each
hard disk storage can have different partitions, which are identified by a
number. For instance, sda1 is the first partition of the first hard disk
storage.
As you can see, the School’s system has one hard disk storage with 3
partitions.
Who select these names for devices? Are there any standards? Can I rename the
file of a device? For instance, can I change the /dev/mem
to /dev/memory
?
Step 2. Standard File Descriptors
There are three files that look like they are devices, but they are not. They
are file descriptors (numbers) that are connected to either a normal file or a
special file (device):
Traditionally, /dev/fd/0
or /dev/stdin
was connected to keyboard
device, meaning that reading from keyboard file (device) was the same as
reading from /dev/fd/0
or /dev/stdin
file descriptors. /dev/fd/1
or /dev/stdout
was connected to printing device or monitor, meaning that
writing to printer file (device) was the same as writing to /dev/fd/1
or /dev/stdout
file descriptors; likewise, for /dev/fd/2
and /dev/stderr
to print out errors. Why not use special files’ names directly for keyboard
or printer instead of working with these numbers? Very good question!
Working with special files (device) requires somebody to be next to the
School’s computer system. For instance, if you want to read from the keyboard
from its assigned special file.
Somebody should be in the School’s server room and press any keys in the
keyboard device attached to the School’s computer system. This is not
convenient for us when we connect remotely to a computer system.
Therefore, by default, UNIX-based/like operating system developers came up
with the idea of standardizing the input and output for programs regardless of
where or what the actual device is. So, they fixed these three file
descriptors that can be connected to any special file (device) or normal file.
For the program, it does not matter.
The program reads from 0 and writes to 1. If error, the program writes to 2.
You may connect 0 and 1 and 2, all to a normal file (how?). Then your program
reads input from the file and writes output and errors, if any, to the same
file.
But how do we run our program, like the one in Lab03, at School’s computer
system that reads input and writes outputs? This is handled by either kernel
or shell, who attach standard file descriptors to a virtual terminal device
called tty (TeleTYpewriter) with a unique number for a user connected to the
computer system. This virtual device is the window with the black background
that shows you the shell command prompt.
You can see your virtual terminal device number by using the tty command:
This is the device your program reads from or writes to, not the keyboard or
monitor at the School’s server room or at your home!
When your program, like in Lab03, asks an input value, it reads from 0 which
is connected to your tty. So, when you type numbers or characters by your
keyboard attached to your computer at home, it goes to your tty, and then it
forwards them to your program. Can you explain what happens when your program
writes outputs and you see it in your monitor?
Step 3. Read/Write to Devices as Files via Shell
vi is a program to open normal files that are stored in storage devices. But
it cannot open special files (devices) and simply raise an error. However,
UNIX, which claims that devices are files, must provide the same system calls
to work with devices the same way as files. In the next step, we’ll see UNIX
fulfills its promise. Not only that, now we see that its shell also provides a
built-in command cat (concatenate)to do the operations on devices and files in
the same way.
To read from a normal file or a special file (device), you can simply use cat
followed by the name of the file/device.
As seen, we do not have enough permission to read from some devices. But we
have permission to access our assigned virtual terminal device tty. Let’s find
our unique tty again:
Then, read from it.
As seen, it is empty initially. You can put some data to it by typing and
pressing enter:
You see that the cat reads from the tty and shows it to us. You can continue
to send more info to the tty and cat reads them and show them to you. You can
exit cat by CTRL+C.
I used cat on my first hard disk storage on my own computer system, and here
is the output:
Technically, cat opens the special file (device) sda1, reads the content and
writes them into 1 which is connected to tty, and you can see the content of
my hard disk drive.
Let’s write to a device. You can use cat with ] operator that connects 1 to a
device instead of your tty. Then, you are able to input data and it writes
them to that device:
As seen, you are not able to write to memory due to lack of enough permission.
However, you can write to your tty.
You see the same effect as when you read from tty. Can you explain what is
happening?
I don’t dare to write on my hard disk storage by cat! But I can write to my
sound device, whose file is /dev/dsp
.
I have to exit cat
to hear my sound device. If you do it on your sound
card, you will hear nothing but a loud noise! This is because the sound device
needs audio signals and cannot read my sentences in English. To send an audio
signal to my sound device:
- I record my voice in a file test.wav
- I send the content of this file to the sound device cat can connect two files/devices by reading from one file or device (source) and write it into the second file or device (target). For example,
Which reads from the file test.c and writes it to your tty device. Now, I want
to send my test.wav to my sound device:
Great! Please note that we cannot do this on the School’s computer system due
to lack of permission. You can try it yourself if you have UNIX-base/like OS
or UNIX emulator software (e.g., Cygwin 1 on Windows.)
Step 4. Read/Write to Devices as Files via System Calls
Now that we know how devices and files are treated the same in UNIX, let’s
open a device and read from or write to it like a normal file in a C program.
Due to our lack of enough permission on the School’s computer system, we use
the virtual terminal device tty in our example. First, we need to know the tty
number that assigned to our terminal:
Now, /dev/pts/9
is our read and write device. First, we need to open it
and have a file descriptor to the device.
The open system call is in the file control header (fcntl.h):
Then, we need to read from it using the file descriptor at hand. The read
system call is in UNIX standard header (unistd.h):
There are two tasks for your submission:
Our example in step 4 never stops. Add lines of code such that when the user
writes END, it exits the while loop, safely closes the device, and returns.
- Instead of printing what we read from the device to output (the terminal device itself), write them into a normal file, named log.txt.
You are not allowed to use any library routines, no stdio.h! Only system calls
in fcntl.h and unistd.h. The sample code for step 4 has been attached in a zip
file named lab06_hfani.zip.
Deliverables
You will prepare and submit the program in one single zip file
lab06_uwinid.zip containing the following items:
- lab06_uwinid.zip
- tty.c => built with no error
- log.txt => the output of the program
- results.pdf/jpg/png => the image snapshot of the program run
- (Optional) readme.txt
- Files Naming and Formats
Please follow the naming convention as you lose marks otherwise. Instead of
uwinid, use your own account name.