您正在查看: unix 分类下的文章

chapter 21


Chapter 21

21.5

Here are some hints. There are two places to check for queued jobs: the printer spooling daemon's queue and the network printer's internal queue. Take care to prevent one user from being able to cancel someone else's print job. Of course, the superuser should be able to cancel any job.

chapter 17


Chapter 17

17.3

A declaration specifies the attributes (such as the data type) of a set of identifiers. If the declaration also causes storage to be allocated, it is called a definition.

In the opend.h header, we declare the three global variables with the extern storage class. These declarations do not cause storage to be allocated for the variables. In the main.c file, we define the three global variables. Sometimes, we'll also initialize a global variable when we define it, but we typically let the C default apply.

17.5

Both select and poll return the number of ready descriptors as the value of the function. The loop that goes through the client array can terminate when the number of ready descriptors have been processed.

chapter 18


Chapter 18

18.1

Note that you have to terminate the reset command with a line feed character, not a return, since the terminal is in noncanonical mode.

18.2

It builds a table for each of the 128 characters and sets the high-order bit (the parity bit) according to the user's specification. It then uses 8-bit I/O, handling the parity generation itself.

18.3

If you happen to be on a windowing terminal, you don't need to log in twice. You can do this experiment between two separate windows. Under Solaris, execute stty -a with standard input redirected from the terminal window running vi. This shows that vi sets MIN to 1 and TIME to 1. A call to read will wait for at least one character to be typed, but after that character is entered, read waits only one-tenth of a second for additional characters before returning.

chapter 19


Chapter 19

19.1

Both servers, telnetd and rlogind, run with superuser privileges, so their calls to chown and chmod succeed.

19.3

Execute pty -n stty -a to prevent the slave's termios structure and winsize structure from being initialized.

19.5

Unfortunately, the F_SETFL command of fcntl doesn't allow the readwrite status to be changed.

19.6

There are three process groups: (1) the login shell, (2) the pty parent and child, and (3) the cat process. The first two process groups constitute a session with the login shell as the session leader. The second session contains only the cat process. The first process group (the login shell) is a background process group, and the other two are foreground process groups.

19.7

First, cat terminates when it receives the end of file from its line discipline. This causes the PTY slave to terminate, which causes the PTY master to terminate. This in turn generates an end of file for the pty parent that's reading from the PTY master. The parent sends SIGTERM to the child, so the child terminates next. (The child doesn't catch this signal.) Finally, the parent calls exit(0) at the end of the main function.

The relevant output from the program shown in Figure 8.29 is

  cat e =270, chars =274, stat =0:
  pty e =262, chars = 40, stat =  15: F  X
  pty e =288, chars =188, stat =0:
19.8

This can be done with the shell's echo command and the date(1) command, all in a subshell:

#!/bin/sh
( echo "Script started on " 'date';
  pty "${SHELL:-/bin/sh}";
  echo "Script done on " 'date' ) | tee typescript
19.9

The line discipline above the PTY slave has echo enabled, so whatever pty reads on its standard input and writes to the PTY master gets echoed by default. This echoing is done by the line discipline module above the slave even though the program (ttyname) never reads the data.

chapter 20


Chapter 20

20.1

Our conservative locking in _db_dodelete is to avoid race conditions with db_nextrec. If the call to _db_writedat were not protected with a write lock, it would be possible to erase the data record while db_nextrec was reading that data record: db_nextrec would read an index record, determine that it was not blank, and then read the data record, which could be erased by _db_dodelete between the calls to _db_readidx and _db_readdat in db_nextrec.

20.2

Assume that db_nextrec calls _db_readidx, which reads the key into the index buffer for the process. This process is then stopped by the kernel, and another process runs. This other process calls db_delete, and the record being read by the other process is deleted. Both its key and its data are rewritten in the two files as all blanks. The first process resumes and calls _db_readdat (from db_nextrec) and reads the all-blank data record. The read lock by db_nextrec allows it to do the read of the index record, followed by the read of the data record, as an atomic operation (with regard to other cooperating processes using the same database).

20.3

With mandatory locking, other readers and writers are affected. Other reads and writes are blocked by the kernel until the locks placed by _db_writeidx and _db_writedat are removed.

20.5

By writing the data record before the index record, we protect ourselves from generating a corrupt record if the process should be killed in between the two writes. If the process were to write the index record first, but be killed before writing the data record, then we'd have a valid index record that pointed to invalid data.