6. Devices
- A device driver hides the hardware device’s communication
protocols from the operating system and allows the system to interact with the
device through a standardized interface. - Processes can communicate with a device driver via
file-like objects.
6.1 Device Types
- A character device represents a hardware device that reads
or writes a serial stream of data bytes. - A block device represents a hardware device that reads or
writes data in fixed-size blocks.
6.2 Device Numbers
- Linux identifies devices using two numbers: the major
device number and the minor device number. - The major device number specifies which driver the device
corresponds to. - Minor device numbers distinguish individual devices or
components controlled by a single driver. - The special entry /proc/devices lists major device numbers
corresponding to active device drivers currently loaded into the kernel.
[liuchao@localhost ~]$ cat /proc/devices
Character devices:
1
mem
4
/dev/vc/0
4
tty
4
ttyS
5
/dev/tty
5
/dev/console
5
/dev/ptmx
6
lp
7
vcs
10
misc
13
input
14
sound
21
sg
29
fb
99
ppdev
116 alsa
128 ptm
136 pts
180 usb
189 usb_device
216 rfcomm
254 pcmcia
Block devices:
1
ramdisk
1
ramdisk
2
fd
8
sd
9
md
22
ide1
65
sd
66
sd
67
sd
68
sd
69
sd
70
sd
71
sd
128 sd
129 sd
130 sd
131 sd
132 sd
133 sd
134 sd
135 sd
253 device-mapper
254 mdp
6.3 Device Entries
- Only superuser processes can create block and character
devices using the mknod command or the mknod system call. - To create a device using the mknod command
- The first argument is the path of the entry in the file
system. - The second argument is b for a block device or c for a
character device. - Provide the major and minor device numbers as the third
and fourth arguments.
% mknod ./lp0 c 6 0
- The ls command displays device entries specially.
% ls -l lp0
c(b for block device and c for character
device)rw-r----- 1 root root 6, 0(major and minor device numbers) Mar 7 17:03
lp0
- To remove the entry, use rm.
% rm ./lp0
- The /dev Directory
[liuchao@localhost ~]$ ls -all /dev/
total 8
drwxr-xr-x 12 root root
3840 Aug 2 13:22 .
drwxr-xr-x 24 root root
4096 Aug 2 13:20 ..
crw-rw----
1 root root 14,
12 Aug 2 13:20 adsp
crw-------
1 root root 10, 175 Aug
2 13:20 agpgart
crw-------
1 liuchao root 14, 4 Aug
2 13:20 audio
drwxr-xr-x
3 root root 60 Aug
2 13:20 bus
lrwxrwxrwx
1 root root 3 Aug
2 13:20 cdrom -> hdc
lrwxrwxrwx
1 root root 3 Aug
2 13:20 cdrom-hdc -> hdc
crw-------
1 liuchao root 5, 1 Aug
2 13:20 console
lrwxrwxrwx
1 root root 11 Aug
2 13:20 core -> /proc/kcore
drwxr-xr-x
6 root root 120 Aug
2 13:20 disk
brw-r-----
1 root disk 253,
0 Aug 2 2008 dm-0
brw-r-----
1 root disk 253,
1 Aug 2 2008 dm-1
crw-rw----
1 root root 14,
9 Aug 2 13:20 dmmidi
crw-------
1 liuchao root 14, 3 Aug
2 13:20 dsp
lrwxrwxrwx
1 root root 13 Aug
2 13:20 fd -> /proc/self/fd
brw-rw----
1 liuchao floppy 2, 0 Aug
2 13:20 fd0
brw-rw----
1 liuchao floppy 2, 84 Aug
2 13:20 fd0u1040
brw-rw----
1 liuchao floppy 2, 88 Aug
2 13:20 fd0u1120
brw-rw----
1 liuchao floppy 2, 28 Aug
2 13:20 fd0u1440
brw-rw----
1 liuchao floppy 2, 44 Aug
2 13:20 fd0u1680
brw-rw----
1 liuchao floppy 2, 60 Aug
2 13:20 fd0u1722
brw-rw----
1 liuchao floppy 2, 76 Aug
2 13:20 fd0u1743
brw-rw----
1 liuchao floppy 2, 96 Aug
2 13:20 fd0u1760
brw-rw----
1 liuchao floppy 2, 116 Aug 2 13:20 fd0u1840
brw-rw----
1 liuchao floppy 2, 100 Aug 2 13:20 fd0u1920
brw-rw----
1 liuchao floppy 2, 12 Aug
2 13:20 fd0u360
brw-rw----
1 liuchao floppy 2, 16 Aug
2 13:20 fd0u720
brw-rw----
1 liuchao floppy 2, 120 Aug 2 13:20 fd0u800
brw-rw----
1 liuchao floppy 2, 52 Aug
2 13:20 fd0u820
brw-rw----
1 liuchao floppy 2, 68 Aug
2 13:20 fd0u830
lrwxrwxrwx
1 root root
3 Aug 2 13:20 floppy-fd0 ->
fd0
crw-rw-rw-
1 root root 1,
7 Aug 2 13:20 full
srwx------
1 liuchao root 0 Aug 2 13:21 gpmctl
brw-------
1 liuchao disk 22, 0 Aug
2 13:20 hdc
crw-------
1 root root 10, 228 Aug
2 13:20 hpet
prw-------
1 root root 0 Aug
2 13:22 initctl
drwxr-xr-x
2 root root 120 Aug
2 13:20 input
crw-------
1 root root 1,
11 Aug 2 13:20 kmsg
srw-rw-rw-
1 root root 0 Aug
2 13:21 log
brw-r-----
1 root disk 7,
0 Aug 2 13:20 loop0
brw-r-----
1 root disk 7,
1 Aug 2 13:20 loop1
brw-r-----
1 root disk 7,
2 Aug 2 13:20 loop2
brw-r-----
1 root disk 7,
3 Aug 2 13:20 loop3
brw-r-----
1 root disk 7,
4 Aug 2 13:20 loop4
brw-r-----
1 root disk 7,
5 Aug 2 13:20 loop5
brw-r-----
1 root disk 7,
6 Aug 2 13:20 loop6
brw-r-----
1 root disk 7,
7 Aug 2 13:20 loop7
crw-rw----
1 root lp 6,
0 Aug 2 13:20 lp0
lrwxrwxrwx
1 root root 13 Aug
2 13:20 MAKEDEV -> /sbin/MAKEDEV
drwxr-xr-x
2 root root 100 Aug
2 2008 mapper
brw-r-----
1 root disk 9,
0 Aug 2 13:20 md0
crw-r-----
1 root kmem 1,
1 Aug 2 13:20 mem
crw-------
1 liuchao root 14, 2 Aug
2 13:20 midi
crw-------
1 liuchao root 14, 0 Aug
2 13:20 mixer
drwxr-xr-x
2 root root 60 Aug
2 13:20 net
crw-rw-rw-
1 root root 1,
3 Aug 2 13:20 null
crw-rw----
1 root root 10, 144 Aug
2 13:20 nvram
lrwxrwxrwx
1 root root 3 Aug
2 13:20 par0 -> lp0
crw-rw----
1 root lp 99,
0 Aug 2 13:20 parport0
crw-rw----
1 root lp 99,
1 Aug 2 13:20 parport1
crw-rw----
1 root lp 99,
2 Aug 2 13:20 parport2
crw-rw----
1 root lp 99,
3 Aug 2 13:20 parport3
crw-r-----
1 root kmem 1,
4 Aug 2 13:20 port
crw-------
1 root root 108,
0 Aug 2 13:20 ppp
crw-rw-rw-
1 root tty 5,
2 Aug 2 13:42 ptmx
drwxr-xr-x
2 root root 0 Aug 2 2008
pts
lrwxrwxrwx
1 root root 4 Aug
2 13:20 ram -> ram1
brw-r-----
1 root disk 1,
0 Aug 2 2008 ram0
brw-r-----
1 root disk 1,
1 Aug 2 2008 ram1
brw-r-----
1 root disk 1,
10 Aug 2 2008 ram10
brw-r----- 1 root
disk 1, 11 Aug
2 2008 ram11
brw-r-----
1 root disk 1,
12 Aug 2 2008 ram12
brw-r-----
1 root disk 1,
13 Aug 2 2008 ram13
brw-r-----
1 root disk 1,
14 Aug 2 2008 ram14
brw-r-----
1 root disk 1,
15 Aug 2 2008 ram15
brw-r-----
1 root disk 1,
2 Aug 2 2008 ram2
brw-r-----
1 root disk 1,
3 Aug 2 2008 ram3
brw-r-----
1 root disk 1,
4 Aug 2 2008 ram4
brw-r-----
1 root disk 1,
5 Aug 2 2008 ram5
brw-r-----
1 root disk 1,
6 Aug 2 2008 ram6
brw-r-----
1 root disk 1,
7 Aug 2 2008 ram7
brw-r-----
1 root disk 1,
8 Aug 2 2008 ram8
brw-r-----
1 root disk 1,
9 Aug 2 2008 ram9
lrwxrwxrwx
1 root root 4 Aug
2 13:20 ramdisk -> ram0
crw-rw-rw-
1 root root 1,
8 Aug 2 13:20 random
brw-------
1 root root 253,
0 Aug 2 2008 root
crw-r--r--
1 root root 10, 135 Aug
2 2008 rtc
brw-r-----
1 root disk 8,
0 Aug 2 2008 sda
brw-r----- 1 root
disk 8, 1 Aug
2 13:20 sda1
brw-r-----
1 root disk 8,
2 Aug 2 2008 sda2
crw-------
1 liuchao root 14, 1 Aug
2 13:20 sequencer
crw-rw----
1 root root 14,
8 Aug 2 13:20 sequencer2
crw-------
1 root root 21,
0 Aug 2 13:20 sg0
drwxrwxrwt
2 root root 40 Aug
2 13:20 shm
drwxr-xr-x
2 root root 180 Aug
2 13:20 snd
lrwxrwxrwx
1 root root 15 Aug
2 13:20 stderr -> /proc/self/fd/2
lrwxrwxrwx
1 root root 15 Aug
2 13:20 stdin -> /proc/self/fd/0
lrwxrwxrwx
1 root root 15 Aug
2 13:20 stdout -> /proc/self/fd/1
crw-------
1 root root 4,
0 Aug 2 2008 systty
crw-rw-rw-
1 root tty 5,
0 Aug 2 13:20 tty
crw-rw----
1 root root 4,
0 Aug 2 2008 tty0
crw-------
1 root root 4,
1 Aug 2 13:21 tty1
crw-rw----
1 root tty 4,
10 Aug 2 2008 tty10
crw-rw----
1 root tty 4,
11 Aug 2 2008 tty11
crw-rw----
1 root tty 4,
12 Aug 2 2008 tty12
crw-rw----
1 root tty 4,
13 Aug 2 13:20 tty13
crw-rw----
1 root tty 4,
14 Aug 2 13:20 tty14
crw-rw----
1 root tty 4,
15 Aug 2 13:20 tty15
crw-rw----
1 root tty 4,
16 Aug 2 13:20 tty16
crw-rw----
1 root tty 4,
17 Aug 2 13:20 tty17
crw-rw----
1 root tty 4,
18 Aug 2 13:20 tty18
crw-rw----
1 root tty 4,
19 Aug 2 13:20 tty19
crw-------
1 root root 4,
2 Aug 2 13:21 tty2
crw-rw----
1 root tty 4,
20 Aug 2 13:20 tty20
crw-rw----
1 root tty 4,
21 Aug 2 13:20 tty21
crw-rw----
1 root tty 4,
22 Aug 2 13:20 tty22
crw-rw----
1 root tty 4,
23 Aug 2 13:20 tty23
crw-rw----
1 root tty 4,
24 Aug 2 13:20 tty24
crw-rw----
1 root tty 4,
25 Aug 2 13:20 tty25
crw-rw----
1 root tty 4,
26 Aug 2 13:20 tty26
crw-rw----
1 root tty 4,
27 Aug 2 13:20 tty27
crw-rw----
1 root tty 4,
28 Aug 2 13:20 tty28
crw-rw----
1 root tty 4,
29 Aug 2 13:20 tty29
crw-------
1 root root 4,
3 Aug 2 13:21 tty3
crw-rw----
1 root tty 4,
30 Aug 2 13:20 tty30
crw-rw----
1 root tty 4,
31 Aug 2 13:20 tty31
crw-rw----
1 root tty 4,
32 Aug 2 13:20 tty32
crw-rw----
1 root tty 4,
33 Aug 2 13:20 tty33
crw-rw----
1 root tty 4,
34 Aug 2 13:20 tty34
crw-rw----
1 root tty 4,
35 Aug 2 13:20 tty35
crw-rw----
1 root tty 4,
36 Aug 2 13:20 tty36
crw-rw----
1 root tty 4,
37 Aug 2 13:20 tty37
crw-rw----
1 root tty 4,
38 Aug 2 13:20 tty38
crw-rw----
1 root tty 4,
39 Aug 2 13:20 tty39
crw-------
1 root root 4,
4 Aug 2 13:21 tty4
crw-rw----
1 root tty 4,
40 Aug 2 13:20 tty40
crw-rw----
1 root tty 4,
41 Aug 2 13:20 tty41
crw-rw----
1 root tty 4,
42 Aug 2 13:20 tty42
crw-rw----
1 root tty 4,
43 Aug 2 13:20 tty43
crw-rw----
1 root tty 4,
44 Aug 2 13:20 tty44
crw-rw----
1 root tty 4,
45 Aug 2 13:20 tty45
crw-rw----
1 root tty 4,
46 Aug 2 13:20 tty46
crw-rw----
1 root tty 4,
47 Aug 2 13:20 tty47
crw-rw----
1 root tty 4,
48 Aug 2 13:20 tty48
crw-rw----
1 root tty 4,
49 Aug 2 13:20 tty49
crw-------
1 root root 4,
5 Aug 2 13:21 tty5
crw-rw----
1 root tty 4,
50 Aug 2 13:20 tty50
crw-rw----
1 root tty 4,
51 Aug 2 13:20 tty51
crw-rw----
1 root tty 4,
52 Aug 2 13:20 tty52
crw-rw----
1 root tty 4,
53 Aug 2 13:20 tty53
crw-rw----
1 root tty 4,
54 Aug 2 13:20 tty54
crw-rw----
1 root tty 4,
55 Aug 2 13:20 tty55
crw-rw----
1 root tty 4,
56 Aug 2 13:20 tty56
crw-rw----
1 root tty 4,
57 Aug 2 13:20 tty57
crw-rw----
1 root tty 4,
58 Aug 2 13:20 tty58
crw-rw----
1 root tty 4,
59 Aug 2 13:20 tty59
crw-------
1 root root 4,
6 Aug 2 13:21 tty6
crw-rw----
1 root tty 4,
60 Aug 2 13:20 tty60
crw-rw----
1 root tty 4,
61 Aug 2 13:20 tty61
crw-rw----
1 root tty 4,
62 Aug 2 13:20 tty62
crw-rw----
1 root tty 4,
63 Aug 2 13:20 tty63
crw-rw----
1 root root 4,
7 Aug 2 2008 tty7
crw-rw----
1 root root 4,
8 Aug 2 13:20 tty8
crw-rw----
1 root tty 4,
9 Aug 2 2008 tty9
crw-rw----
1 root uucp 4,
64 Aug 2 2008 ttyS0
crw-rw----
1 root uucp 4,
65 Aug 2 2008 ttyS1
crw-rw----
1 root uucp 4,
66 Aug 2 2008 ttyS2
crw-rw----
1 root uucp 4,
67 Aug 2 2008 ttyS3
drwxr-xr-x
4 root root 80 Aug
2 13:33 .udev
cr--r--r--
1 root root 1,
9 Aug 2 13:20 urandom
crw-------
1 vcsa tty 7,
0 Aug 2 13:20 vcs
crw-------
1 vcsa tty 7,
1 Aug 2 13:21 vcs1
crw-------
1 vcsa tty 7,
2 Aug 2 13:21 vcs2
crw-------
1 vcsa tty 7,
3 Aug 2 13:21 vcs3
crw-------
1 vcsa tty 7,
4 Aug 2 13:21 vcs4
crw-------
1 vcsa tty 7,
5 Aug 2 13:21 vcs5
crw-------
1 vcsa tty 7,
6 Aug 2 13:21 vcs6
crw-------
1 vcsa tty 7,
7 Aug 2 13:22 vcs7
crw-------
1 vcsa tty 7,
8 Aug 2 13:20 vcs8
crw-------
1 vcsa tty 7, 128 Aug 2 13:20 vcsa
crw-------
1 vcsa tty 7, 129 Aug 2 13:21 vcsa1
crw-------
1 vcsa tty 7, 130 Aug 2 13:21 vcsa2
crw-------
1 vcsa tty 7, 131 Aug 2 13:21 vcsa3
crw-------
1 vcsa tty 7, 132 Aug 2 13:21 vcsa4
crw-------
1 vcsa tty 7, 133 Aug 2 13:21 vcsa5
crw-------
1 vcsa tty 7, 134 Aug 2 13:21 vcsa6
crw-------
1 vcsa tty 7, 135 Aug 2 13:22 vcsa7
crw-------
1 vcsa tty 7, 136 Aug 2 13:20 vcsa8
drwx------
2 root root 80 Aug
2 13:20 VolGroup00
lrwxrwxrwx
1 root root 4 Aug
2 13:20 X0R -> null
crw-rw-rw-
1 root root 1, 5 Aug
2 13:20 zero
- Accessing Devices by Opening Files
int fd = open (“/dev/lp0”, O_WRONLY);
write (fd, buffer, buffer_length);
close (fd);
6.4 Hardware Devices
- Partial Listing of Common Block Devices
Device |
Name |
Major |
Minor |
First floppy drive |
/dev/fd0 |
2 |
0 |
Second floppy drive |
/dev/fd1 |
2 |
1 |
Primary IDE controller, master device |
/dev/hda |
3 |
0 |
Primary IDE controller, master device, |
/dev/hda1 |
3 |
1 |
Primary IDE controller, secondary device |
/dev/hdb |
3 |
64 |
Primary IDE controller, secondary device, |
/dev/hdb1 |
3 |
65 |
Secondary IDE controller, master device |
/dev/hdc |
22 |
0 |
Secondary IDE controller, secondary |
/dev/hdd |
22 |
64 |
First SCSI drive |
/dev/sda |
8 |
0 |
First SCSI drive, first partition |
/dev/sda1 |
8 |
1 |
Second SCSI disk |
/dev/sdb |
8 |
16 |
Second SCSI disk, first partition |
/dev/sdb1 |
8 |
17 |
First SCSI CD-ROM drive |
/dev/scd0 |
11 |
0 |
Second SCSI CD-ROM drive |
/dev/scd1 |
11 |
1 |
- Some Common Character Devices
Device |
Name |
Major |
Minor |
Parallel port 0 |
/dev/lp0 or /dev/par0 |
6 |
0 |
Parallel port 1 |
/dev/lp1 or /dev/par1 |
6 |
1 |
First serial port |
/dev/ttyS0 |
4 |
64 |
Second serial port |
/dev/ttyS1 |
4 |
65 |
IDE tape drive |
/dev/ht0 |
37 |
0 |
First SCSI tape drive |
/dev/st0 |
9 |
0 |
Second SCSI tape drive |
/dev/st1 |
9 |
1 |
System console |
/dev/console |
5 |
1 |
First virtual terminal |
/dev/tty1 |
4 |
1 |
Second virtual terminal |
/dev/tty2 |
4 |
2 |
Process’s current terminal device |
/dev/tty |
5 |
0 |
Sound card |
/dev/audio |
14 |
4 |
6.5 Special Devices
6.5.1. /dev/null
- Linux discards any data written to /dev/null.
Run a command and discard its standard
output, redirect standard output to /dev/null:
% verbose_command > /dev/null
- Reading from /dev/null always results in an end-of-file.
If you copy from /dev/null to another file,
the destination will be a zero-length file:
% cp /dev/null empty-file
% ls -l empty-file
-rw-rw---- 1 samuel samuel 0 Mar 8 00:27
empty-file
6.5.2. /dev/zero
- The device entry /dev/zero behaves as if it were an
infinitely long file filled with 0 bytes. - As much data as you’d try to read from /dev/zero, Linux
“generates” enough 0 bytes.
% ./hexdump /dev/zero
0x000000 : 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00
0x000010 : 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00
0x000020 : 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00
0x000030 : 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00
...
- Memory mapping /dev/zero is an advanced technique for
allocating memory.
6.5.3. /dev/full
- The entry /dev/full behaves as if it were a file on a file
system that has no more room. - A write to /dev/full fails and sets errno to ENOSPC.
% cp /etc/fstab /dev/full
cp: /dev/full: No space left on device
6.5.4. Random Number Devices
- The rand function actually generates pseudorandom numbers.
- By measuring the time delay between your input actions,
Linux is capable of generating an unpredictable stream of high-quality random
numbers. - You can access this stream by reading from /dev/random and
/dev/urandom. - When Linux exhausts its store of randomness by reading a
large number of bytes from /dev/random, Linux blocks the read operation.
Try displaying the contents of /dev/random
using the od command
% od -t x1 /dev/random
0000000 2c 9c 7a db 2e 79 3d 65 36 c2 e3 1b
52 75 1e 1a
0000020 d3 6d 1e a7 91 05 2d 4d c3 a6 de 54
29 f4 46 04
0000040 b3 b0 8d 94 21 57 f3 90 61 dd 26 ac
94 c3 b9 3a
0000060 05 a3 02 cb 22 0a bc c9 45 dd a6 59
40 22 53 d4
The output will eventually pause when Linux
exhausts its store of randomness. Now try moving your mouse or typing on the
keyboard, and watch additional random numbers appear.
- A read from /dev/urandom will never block.
- If Linux runs out of randomness, it uses a cryptographic
algorithm to generate pseudorandom bytes from the past sequence of random
bytes. - Function to Generate a Random Number from /dev/random
#include <assert.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
/* Return a random integer between MIN and
MAX, inclusive. Obtain
randomness from /dev/random. */
int random_number (int min, int max)
{
/* Store a file descriptor opened to /dev/random in a static variable. That way, we don’t need to open the file every time
this function is called. */
static int dev_random_fd = -1;
char* next_random_byte;
int bytes_to_read;
unsigned random_value;
/* Make sure MAX is greater than MIN. */
assert (max > min);
/* If this is the first time this function is called, open a file descriptor to /dev/random. */
if (dev_random_fd == -1) {
dev_random_fd = open (“/dev/random”, O_RDONLY);
assert (dev_random_fd != -1);
}
/* Read enough random bytes to fill an integer variable. */
next_random_byte = (char*) &random_value;
bytes_to_read = sizeof (random_value);
/* Loop until we’ve read enough bytes. Because /dev/random is filled from user-generated actions, the read may block and may only return a single random byte at a time. */
do {
int bytes_read;
bytes_read = read (dev_random_fd, next_random_byte, bytes_to_read);
bytes_to_read -= bytes_read;
next_random_byte += bytes_read;
} while (bytes_to_read > 0);
/* Compute a random number in the correct range. */
return min + (random_value % (max - min + 1));
}
int main(int argc, char * argv)
{
while(1)
{
int random = random_number(10,
20);
printf("Get a random
number : %d/n",random);
}
}
- Run the program compiled from the above code.
[liuchao@localhost Ramdom]$ ./random_number
Get a random number : 11
Get a random number : 17
Get a random number : 11
Get a random number : 18
Get a random number : 13
Get a random number : 11
Get a random number : 14
Get a random number : 20
- Type something randomly in the terminal, and the result
will be
[liuchao@localhost Ramdom]$ ./random_number
Get a random number : 11
Get a random number : 17
Get a random number : 11
Get a random number : 18
Get a random number : 13
Get a random number : 11
Get a random number : 14
Get a random number : 20
Get a random number : 19
Get a random number : 11
Get a random number : 16
Get a random number : 14
Get a random number : 12
Get a random number : 18
Get a random number : 12
Get a random number : 15
Get a random number : 17
Get a random number : 13
Get a random number : 15
Get a random number : 11
Get a random number : 11
Get a random number : 16