Professional Documents
Culture Documents
Operating Systems 3rd Edition Nutt Solutions Manual instant download all chapter
Operating Systems 3rd Edition Nutt Solutions Manual instant download all chapter
Operating Systems 3rd Edition Nutt Solutions Manual instant download all chapter
Solutions Manual
Go to download the full and correct content document:
https://testbankdeal.com/product/operating-systems-3rd-edition-nutt-solutions-manual
/
More products digital (pdf, epub, mobi) instant
download maybe you interests ...
https://testbankdeal.com/product/operating-systems-3rd-edition-
nutt-test-bank/
https://testbankdeal.com/product/operating-systems-3rd-edition-
deitel-solutions-manual/
https://testbankdeal.com/product/operating-systems-design-and-
implementation-3rd-edition-tanenbaum-solutions-manual/
https://testbankdeal.com/product/understanding-operating-
systems-7th-edition-mchoes-solutions-manual/
Understanding Operating Systems 8th Edition McHoes
Solutions Manual
https://testbankdeal.com/product/understanding-operating-
systems-8th-edition-mchoes-solutions-manual/
https://testbankdeal.com/product/modern-operating-systems-4th-
edition-tanenbaum-solutions-manual/
https://testbankdeal.com/product/understanding-operating-
systems-5th-edition-mchoes-solutions-manual/
https://testbankdeal.com/product/survey-of-operating-systems-5th-
edition-holcombe-solutions-manual/
https://testbankdeal.com/product/operating-systems-internals-and-
design-principles-9th-edition-stallings-solutions-manual/
Gary Nutt, Operating Systems 3/e
Instructor’s Solutions
1. Here is one solution. Another one uses the monitor to encapsulate the resources rather
than just the entry and exit.
monitor sharedV {
public enter(int i) {set i busy;};
public exit(int i) {set i idle;};
};
p_0() {
...
enter(2);
access V_2;
exit(2)
...
}
p_1() {
...
enter(0);
access V_0
exit(0)
...
enter(2);
access V_2;
exit(2)
...
enter(0);
enter(2);
access V_0
access V_2;
exit(0)
exit(2)
}
p_2() {
...
enter(0);
access V_0
exit(0)
...
enter(1);
access V_1;
exit(1)
...
enter(0);
enter(1);
access V_0
access V_1;
exit(0)
©2004 «GreetingLine»
Gary Nutt, Operating Systems 3/e
Instructor’s Solutions
exit(1)
}
p_3() {
...
enter(1);
access V_1;
exit(1)
...
}
semaphore s0 = 1, s1 = 1, s2 = 1;
...
P_simultaneous(...);
V_simultaneous(...);
p_0() {
...
P_simultaneous(s0, s1);
access V_0 & V_1;
V_simultaneous(s0, s1);
...
}
p_1() {
...
P_simultaneous(s1, s2);
access V_1 & V_2;
V_simultaneous(s0, s1);
...
}
p_2() {
...
P_simultaneous(s0, s2);
access V_0 & V_2;
V_simultaneous(s0, s1);
...
}
monitor semaphore {
private:
int count = 1; /* set to the initial value of the semaphore
*/
condition hold;
public:
P() {count--; if(count <= 0) hold.wait;};
V() {count++; hold.signal:};
};
©2004 «GreetingLine»
Gary Nutt, Operating Systems 3/e
Instructor’s Solutions
4. Condition variables are just signaling semaphores (such as the full/empty semaphores
in the bounded buffer problem). The solution to this problem requires that you know
how mutual exclusion is implemented in the monitor. Then the condition variable
wait code must enqueue the thread and release the mutual exclusion. Similarly, the
signal code obtains mutually exclusive access to the monitor and dequeues a thread.
You will need to provide some guidance as to the amount of detail you want as an
acceptable solution to this problem. Here is some pseudo code (that has only been
debugged “by eye”):
struct monitor_t {
private:
semaphore mutex = 1;
int cv = 0;
<ADT data structures>
...
public:
proc_i(...) {
P(mutex);
<processing for proc_i>
/* CV wait */
cv--;
while(cv < 0) {
enqueue(self, cv_list);
setState(self, blocked);
V(mutex);
yield(); /* Call the scheduler */
P(mutex);
}
/* CV signal */
cv++;
if(cv <= 0) {
pid = dequeue(cv_list);
setState(pid, ready);
V(mutex);
yield(); /* Call the scheduler */
P(mutex);
}
V(mutex);
};
...
};
struct monitor_t {
private:
union semun {
int val;
struct semid_ds *buf;
ushort * array;
} arg;
arg.val = 1; /* Initial value of semaphore */
int mutex;
struct sembuf opns[1];
©2004 «GreetingLine»
Gary Nutt, Operating Systems 3/e
Instructor’s Solutions
int cv = 0; /* You could use an event here, but it will be
* tricky releasing the mutex
*/
<ADT data structures>
...
public:
monitor_t() {
mutex = semget(MY_MONITOR, 1, 0666|IPC_CREATE);
if(mutex < 0)
{
fprintf(stderr, "Semaphore not available\n");
exit(0);
}
if(semctl(id, 0, SETVAL, arg) < 0)
{
fprintf( stderr, "Unable to set semaphore value\n");
}
/* Set up the sembuf structure. */
opns[0].sem_num = 0;
opns[0].sem_flg = 0;
};
proc_i(...) {
/* P(mutex) */
opns[0].sem_op = -1;
semop(id, opns, 1);
<processing for proc_i>
/* CV wait */
cv--;
while(cv < 0) {
enqueue(self, cv_list);
setState(self, blocked);
/* V(mutex) */
opns[0].sem_op = 1;
semop(id, opns, 1);
yield(); /* Call the scheduler */
/* P(mutex) */
opns[0].sem_op = -1;
semop(id, opns, 1);
}
/* CV signal */
cv++;
if(cv <= 0) {
pid = dequeue(cv_list);
setState(pid, ready);
/* V(mutex) */
opns[0].sem_op = 1;
semop(id, opns, 1);
yield(); /* Call the scheduler */
/* P(mutex) */
opns[0].sem_op = -1;
semop(id, opns, 1);
}
/* V(mutex) */
opns[0].sem_op = 1;
semop(id, opns, 1);
};
...
©2004 «GreetingLine»
Gary Nutt, Operating Systems 3/e
Instructor’s Solutions
};
struct monitor_t {
private:
HANDLE mutex;
Char *mName = “mutexName”;
int cv = 0;
<ADT data structures>
...
public:
monitor_t() {
mutex = CreateMutex(NULL, FALSE, mName);
};
proc_i(...) {
WaitForSingleObject(mutex, INFINITE); /* P(mutex */
<processing for proc_i>
/* CV wait */
cv--;
while(cv < 0) {
enqueue(self, cv_list);
setState(self, blocked);
ReleaseMutex(mutex); /* V(mutex) */
yield(); /* Call the scheduler */
WaitForSingleObject(mutex, INFINITE); /* P(mutex) */
}
/* CV signal */
cv++;
if(cv <= 0) {
pid = dequeue(cv_list);
setState(pid, ready);
ReleaseMutex(mutex); /* V(mutex) */
yield(); /* Call the scheduler */
WaitForSingleObject(mutex, INFINITE); /* P(mutex) */
}
ReleaseMutex(mutex); /* V(mutex) */
};
...
};
monitor sleepy_barber {
private:
int number_of_customers = 0;
condition_variable haircut, sleepy;
public:
request_haircut {
number_of_customers = number_of_customers + 1;
if (number_of_customers == 1) sleepy.signal;
haircut.wait;
©2004 «GreetingLine»
Gary Nutt, Operating Systems 3/e
Instructor’s Solutions
take_customer {
if (number_of_customers == 0) sleepy.wait;
number_of_customers = number_of_customers - 1;
haircut.signal;
}
8. An asynchronous send operation can be used in any situation in which the sending
process wishes to transmit information to a sender, but it does not care when the
message is received. In the SOR example, the central process can assign work to an
equation solver using an asynchronous send. (The centralized process will ultimately
have to synchronize the completion of the equation solutions by all the solvers, but
the allocation of work need not have synchronization.)
Suppose two processes, p_0 and p_1, cooperate with one another so that they
generally operate independently and concurrently, but they occasionally share
information by p_0 sending information to p_1; with a synchronous send, p_0 can
procede after its send operation with the assurance that p_1 has received the
information. This communication paradigm is used in remote procedure call
(described in detail in Chapter 17).
9. If a set of processes are working on a common problem, i.e., the work has been
partitioned and delegated to various processes, then the run time will be reduced if all
the processes can execute at the same time. This follows because a fixed amount of
work is divided, then two or more processes perform parts of the work simultaneously
(in a system with multiple processors). Blocking receive operations tend to make a
process wait for one or more other processes to "catch up," reducing the effective
amount of concurrency in the execution. However, as we have seen in various
examples in Chapters 8 and 9, concurrent operation on shared information means that
it is necessary to incorporate a synchronization mechanism to manage sharing -- a
factor that considerably raises the complexity of the software.
10. Condition variables are used to suspend a process while it is logically in a critical
section. In a user thread package, the programmer controls the scheduling of threads
within an address space (process). Therefore, the programmer can determine
situations in which a thread is in a critical section, yet needs another critical section,
and thus can suspend the thread from executing until the needed critical section can
©2004 «GreetingLine»
Gary Nutt, Operating Systems 3/e
Instructor’s Solutions
become available. Notice that this is not generally possible at the process level, since
there is not parent to control the schedule and to suspend other processes.
11. The Mach C thread cthread_fork() is similar to UNIX fork() in that it creates a
new thread. It is different in that the thread is given a specific procedure where it will
begin execution (same address space, but a different location from the parent thread).
When the C thread terminates, there is no synchronization with the parent thread.
12. This solution (with minor edits) provided by Don Lindsay, Fall, 1995.
===========================================================================
===========================================================================
/* parent.c
*
* Example program by Don Lindsay
*
*
* This program uses the trapezoidal rule to integrate
* f(x) = 1/(x+1)
* on [0,2]. It does this by forking N processes, each of which
* does n/N trapezoids.
* The parent specifies tasks over N pipes, and recieves answers over one
* shared pipe.
* The parent reports the totalled area, and reports the elapsed integration
* time, ie excluding the setup time. The time is the average of many runs.
* This program must be run with N between 1 and 8, and n=64.
*
* Tested on Linux: portability unknown.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>>
#include <errno.h>
#include <fcntl.h>
#include <math.h>
#ifndef FALSE
#define FALSE 0
#define TRUE 1
#endif
typedef int Boolean;
/*typedef unsigned char u_char;*/
int debug = 0;
©2004 «GreetingLine»
Gary Nutt, Operating Systems 3/e
Instructor’s Solutions
int forkcount;
int pipes_to_child[8][2];
int pipe_from_child[2];
/****************************************************************
*
*/
void fatal( char *string )
{
fprintf( stderr, "FATAL ERROR: %s\\n", string );
exit(1);
}
/****************************************************************
*
*/
void system_fatal( char *string )
{
fprintf( stderr, "FATAL SYSTEM ERROR: ");
perror( string );
exit(1);
}
/****************************************************************
*
*/
void prompt()
{
fprintf( stderr, "TRY: parent N [-d]\\n" );
exit(1);
}
/****************************************************************
*
* Sets globals forkcount, debug
*/
void parse_my_args( int argc, char **argv )
{
if( argc < 2 || argc > 3 ) prompt();
if( argc == 3 ){
if( strcmp( argv[2], "-d" ) == 0 )
debug = 1;
else if( strcmp( argv[2], "-D" ) == 0 )
debug = 2;
else
prompt();
}
forkcount = atoi( argv[1] );
PRINT( stderr, "forkcount %d\\n", forkcount );
if( forkcount < 1 || forkcount > 8 ) fatal( "arg out of range" );
}
/****************************************************************
*
* Fork that many children.
* Leaves global pipes_to_child and pipe_from_child. These are the
* stdin and stdout of each child.
* Exits on error.
*/
void fork_solvers( int forkcount )
{
int i;
pid_t pid;
char *child_argv[2];
child_argv[0] = PATHNAME;
child_argv[1] = NULL;
©2004 «GreetingLine»
Gary Nutt, Operating Systems 3/e
Instructor’s Solutions
if( pipe( pipe_from_child )) system_fatal( "Pipe" );
for( i = 0; i < forkcount; i++ ) {
if( pipe( pipes_to_child[i] )) system_fatal( "Pipe" );
if( close(0))
system_fatal("Close1");
if( dup( pipes_to_child[i][PIPE_IN ])==-1)system_fatal("dup1");
if( close(1))
system_fatal("Close2");
if( dup(pipe_from_child[ PIPE_OUT ])==-1)system_fatal("dup2");
/* Try to get them all working by writing all before any reads */
out_buf = i;
if( write( pipes_to_child[child][PIPE_OUT], &out_buf,1)!=1)
system_fatal( "write" );
}
for( area = 0.0, i = 1; i <= NUMSTEPS; i++ ) {
if( read( pipe_from_child[PIPE_IN], &in_buf,in_buf_len)
!= in_buf_len )
system_fatal( "read pipe" );
PRINT( stderr, "parent: %d gets area = %g\\n", i, in_buf );
area += in_buf;
}
PRINT( stderr, "parent: %d gets area = %g\\n", i, in_buf );
return area;
}
/****************************************************************
*
©2004 «GreetingLine»
Gary Nutt, Operating Systems 3/e
Instructor’s Solutions
*
*/
void kill_solvers( int forkcount )
{
int i;
char out_buf;
out_buf = 0;
start = get_sys_time();
/* Must integrate many times to get a measurable amount of time. */
for( i = 0; i < REPEAT; i++ ) {
area = farm_out_work( forkcount );
}
stop = get_sys_time();
©2004 «GreetingLine»
Gary Nutt, Operating Systems 3/e
Instructor’s Solutions
*/
#define FUNC(x) (1/(x+1.0))
#define NUMSTEPS (64)
#define INTERVAL_LO (0.0)
#define INTERVAL_HI (2.0)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
int debug = 0;
int forkcount;
/****************************************************************
*
*/
void fatal( char *string )
{
fprintf( stderr, "FATAL ERROR: %s\\n", string );
exit(1);
}
/****************************************************************
*
*/
void parse_args( int argc, char **argv )
{
if( argc != 1 ) {
fprintf( stderr, "Illegal arglist to child: %d\\n", argc );
exit(1);
}
}
/****************************************************************
*
*/
void system_fatal( char *string )
{
fprintf( stderr, "CHILD FATAL SYSTEM ERROR: ");
perror( string );
exit(1);
}
©2004 «GreetingLine»
Gary Nutt, Operating Systems 3/e
Instructor’s Solutions
/****************************************************************
*
* Returns the area under f(x1)..f(x2) assuming f is linear between.
* Assumes x2 > x1.
* Expects macro FUNC.
*/
float trapezoid( float x1, float x2 )
{
float f1 = FUNC(x1);
float f2 = FUNC(x2);
return (x2-x1) * (f1+f2)/2.;
}
/****************************************************************
*
* Returns area of indexed trapezoid.
*/
float integrate( int index )
{
float x1, x2, deltax;
13. Here is the quadrature problem using Mach C threads (with politically incorrect name
for the trapezoid solver code).
===========================================================================
===========================================================================
/* Trapezoidal Rule Quadrature using Mach C threads
*
* Use the following command to compile this file
* (assumed to be named trapezoid.c)
*
* trapezoid: trapezoid.o timer.o
* cc -g -o trapezoid trapezoid.o timer.o
*
* trapezoid.o: trapezoid.c
©2004 «GreetingLine»
Gary Nutt, Operating Systems 3/e
Instructor’s Solutions
* cc -c trapezoid.c
*
*/
#include
/* #define TRUE 1 */
#define bottomRange 0.0
#define topRange 2.0
#define intervals 64
#define maxN 8
float getTime();
float currentLeft, currentRight;
float length, result;
float startTime, stopTime;
unsigned lengthSM;
©2004 «GreetingLine»
Gary Nutt, Operating Systems 3/e
Instructor’s Solutions
nAlive = N;
/* Acquired lock */
result = result + shMem[solverNum];
©2004 «GreetingLine»
Gary Nutt, Operating Systems 3/e
Instructor’s Solutions
/* Dispatch new work to the solver that just finished */
if (currentRight+length <= topRange)
{ /* Assign the next segment to the solver */
shMem[iLeft(solverNum)] = currentLeft;
shMem[iRight(solverNum)] = currentRight;
mutex_unlock(segLock[solverNum]);
currentLeft = currentRight;
currentRight = currentRight + length;
}
else
{ /* Eliminate the solver */
shMem[iLeft(solverNum)] = 1.0;
shMem[iRight(solverNum)] = 0.0;
mutex_unlock(segLock[solverNum]);
cthread_join(t_handle[solverNum]);
nAlive--;
};
};
/* All done -- Report the time & result for this iteration */
stopTime = getTime();
printf("%d processes required %6.2f seconds, result = %f\n",
N, stopTime-startTime, result);
exit(0);
}
void solver(me)
int me;
{
float left, right;
float result;
int i;
left = 0.0;
right = 0.0;
while (TRUE)
{
/* Wait for a pair of endpoints */
mutex_lock(segLock[me]);
left = shMem[iLeft(me)];
right = shMem[iRight(me)];
shMem[me] = ((1.0/(left+1.0))+(1.0/(right+1.0)))/2.0*(right-
left);
©2004 «GreetingLine»
Gary Nutt, Operating Systems 3/e
Instructor’s Solutions
mutex_unlock(resultLock[me]);
};
#include <stdio.h>
#include <cthreads.h>
#define MAX_N 4
int N;
main(argc, argv)
int argc;
char *argv[];
{
FILE *data_fp, *fopen();
int i;
int tmp;
double double_eps;
float error, check();
float epsilon;
float solveX();
char data_filename[128];
char host_filename[128];
cthread_t t_handle[MAX_N];
cthread_t cthread_fork();
/* Get data from file; first, get the command line parameters ... */
if(argc == 3)
{
double_eps = atof(argv[1]);
epsilon = double_eps;
strcpy(data_filename, argv[2]);
}
else
{
printf("Usage: chaosMaster \n");
exit(0);
};
©2004 «GreetingLine»
Gary Nutt, Operating Systems 3/e
Instructor’s Solutions
printf("Degree %d is too large, halting ...\n", N);
exit(1);
};
for (i=0;i < N;i++)
fscanf(data_fp,"%f%f%f", &A[i][0], &A[i][1], &A[i][2]);
fscanf(data_fp,"%f %f %f", &b[0], &b[1], &b[2]);
fscanf(data_fp,"%f %f %f", &x[0], &x[1], &x[2]);
fclose(data_fp);
float check(A, x, b, n)
float A[][4], x[], b[];
int n;
{
int i, j;
float sum;
float error;
error = 0.0;
for(i=0; i < n; i++)
{
©2004 «GreetingLine»
Gary Nutt, Operating Systems 3/e
Instructor’s Solutions
sum = 0.0;
for (j=0; j < n; j++)
sum = sum + A[i][j]*x[j];
error = error + (sum - b[i]);
};
if(error<0.0) error = -error;
return(error);
}
cthread_yield();
for(;;)
{
mutex_lock(lock[me]);
x[me] = b[me];
for (j=0;j < N; j++)
if(me!=j) x[me] = x[me] - A[me][j]*x[j];
x[me] = x[me]/A[me][me];
};
}
#include <stdio.h>
#include <signal.h>
#define MAX_N 4
int N;
double A[MAX_N][MAX_N], b[MAX_N];
int xout[MAX_N][2];
int xin[MAX_N][2];
/*******************************************************/
/* Get the command line parameters ... */
if(argc == 3) {
sscanf(argv[1], "%lf", &epsilon);
strcpy(data_filename, argv[2]);
} else {
printf("Usage: sor \n");
exit(1);
©2004 «GreetingLine»
Gary Nutt, Operating Systems 3/e
Instructor’s Solutions
};
printf("\n");
fclose(data_fp);
/*******************************************************/
/* Create the N solvers */
for (i=0; i < N; i++) {
pipe(xin[i]); /* Pipe for solver[i] to return x[i]
*/
pipe(xout[i]); /* Pipe for solver[i] to get x[j] */
if((solverPID[i] = fork()) == 0) {;
solver(i); /* The i-th child runs this code */
exit(1); /* Never get here -- never returns */
};
};
/* The parent continues ... */
/*******************************************************/
/* Iteratively solve the system */
while(check(A, x, b, N) > epsilon) {
/* Distribute the newest x values*/
for (i=0; i < N; i++) {
for(j=0; j < N; j++)
if(j != i)
©2004 «GreetingLine»
Gary Nutt, Operating Systems 3/e
Instructor’s Solutions
write(xout[i][1],
&x[j],sizeof(double));
};
/* Read x[i] from xin[i]. Since we cannot procede beyond
* this loop until ALL solvers have returned a value, we can
* use a blocking read here, i.e., we can wait for all in any order.
*/
for (i=0; i < N; i++)
read(xin[i][0], &x[i], sizeof(double));
};
error = 0.0;
for(i=0; i < n; i++) {
sum = 0.0;
for (j=0; j < n; j++)
sum = sum + A[i][j]*x[j];
error = error + (sum - b[i]);
};
if(error < 0.0) error = -error;
return(error);
}
for(;;) {
/* Get new x values */
for(i=0; i < N; i++)
if(i != me)
read(xout[me][0], &x[i], sizeof(double));
x[me] = b[me];
for (i=0; i < N; i++)
if(i != me) x[me] = x[me] - A[me][i]*x[i];
x[me] = x[me]/A[me][me];
/* Return the new x[me] value */
write(xin[me][1], &x[me], sizeof(double));
};
}
©2004 «GreetingLine»
Gary Nutt, Operating Systems 3/e
Instructor’s Solutions
Makefile:
#CFLAGS = -g -DDEBUG
CFLAGS = -g
CC = cc
SRC =
OBJ = ${SRC:.c=.o}
HDR =
MAINSRC = vt.c
.SUFFIXES: .c.o
.c.o:
${CC} -c ${CFLAGS} $<
${OBJ}: ${HDR}
clean:
rm vt
#include <signal.h>
#include <stdio.h>
#include <termio.h>
#include <unistd.h>
#include <fcntl.h>
#define TRUE 1
#define FALSE 0
#define NUMCOL 80
#define NUMLINES 25
#define NUM_VTS 2
struct vt_status_st {
int line;
int bufchars;
int total_lines_out;
int pid;
int running;
int inputchars;
int awaiting_newinput;
};
void vt_exit_handler()
{
int status;
int pid;
pid = wait(&status);
if(vt_status[0].pid == pid) {
©2004 «GreetingLine»
Gary Nutt, Operating Systems 3/e
Instructor’s Solutions
fprintf(stderr, "vt0 exited\n");
close(pipe_from_child_1[0]);
close(pipe_to_child_1[1]);
vt_status[0].running = 0;
if(vt_status[1].running)
active_vt = 1;
else
exit(0);
}
else if(vt_status[1].pid == pid) {
fprintf(stderr, "vt1 exited\n");
close(pipe_from_child_2[0]);
close(pipe_to_child_2[1]);
vt_status[1].running = 0;
if(vt_status[0].running)
active_vt = 0;
else
exit(0);
}
else
fprintf(stderr, "somone else exited?\n");
void vt_abort()
{
write(STDERR_FILENO, "killing vts\n", 12);
fflush(stderr);
if(close(pipe_from_child_1[0]) == -1)
perror("close cp1 input");
if(close(pipe_to_child_1[1]) == -1)
perror("close pp1 output");
if(close(pipe_from_child_2[0]) == -1)
perror("close cp2 input");
if(close(pipe_to_child_2[1]) == -1)
perror("close pp2 output");
kill(vt_status[0].pid, SIGKILL);
kill(vt_status[1].pid, SIGKILL);
exit(-1);
}
©2004 «GreetingLine»
Gary Nutt, Operating Systems 3/e
Instructor’s Solutions
tinew.c_lflag &= ~(ECHOCTL);
tinew.c_cc[VMIN] = 1;
tinew.c_cc[VTIME] = 0;
if(pipe(pipe_to_child_1) < 0) {
perror("parent pipe 1");
exit(-1);
}
if(pipe(pipe_to_child_2) < 0) {
perror("parent pipe 1");
exit(-1);
}
if(pipe(pipe_from_child_1) < 0) {
perror("child pipe 1");
exit(-1);
}
if(pipe(pipe_from_child_2) < 0) {
perror("child pipe 2");
exit(-1);
}
pid1 = fork();
vt_status[0].pid = pid1;
if (pid1 == 0) {
#ifdef DEBUG
printf("This is child 1\n");
#endif
#ifdef DEBUG
write(pipe_from_child_1[1], "hello", 5);
nbytes = read(pipe_to_child_1[0], buffer, 5);
buffer[nbytes] = '\0';
printf("Child 1 hears parent %s\n", buffer);
#endif
©2004 «GreetingLine»
Gary Nutt, Operating Systems 3/e
Instructor’s Solutions
/* so that read from pipe by VT manager gets data from execed stdout */
dup2(pipe_from_child_1[1], STDOUT_FILENO);
signal(SIGINT, SIG_IGN);
execlp(argv[1], argv[1], (char *)0);
}
else {
#ifdef DEBUG
printf("This is the parent\n");
#endif
pid2 = fork();
vt_status[1].pid = pid2;
if (pid2 == 0) {
#ifdef DEBUG
printf("This is child 2\n");
#endif
#ifdef DEBUG
write(pipe_from_child_2[1], "hello", 5);
nbytes = read(pipe_to_child_2[0], buffer, 5);
buffer[nbytes] = '\0';
printf("Child 2 hears parent %s\n", buffer);
#endif
/* so that read from pipe by VT manager gets data from execed stdout
*/
dup2(pipe_from_child_2[1], STDOUT_FILENO);
signal(SIGINT, SIG_IGN);
execlp(argv[2], argv[2], (char *)0);
}
else {
#ifdef DEBUG
printf("This is the parent\n");
nbytes = read(pipe_from_child_1[0], buffer, 5);
buffer[nbytes] = '\0';
printf("Parent hears child 1 %s\n", buffer);
nbytes = read(pipe_from_child_2[0], buffer, 5);
buffer[nbytes] = '\0';
printf("Parent hears child 2 %s\n", buffer);
write(pipe_to_child_1[1], "hello", 5);
write(pipe_to_child_2[1], "hello", 5);
#endif
©2004 «GreetingLine»
Gary Nutt, Operating Systems 3/e
Instructor’s Solutions
vt_status[0].line = 0;
vt_status[1].line = 0;
vt_status[0].total_lines_out = 0;
vt_status[1].total_lines_out = 0;
vt_status[0].bufchars = 0;
vt_status[1].bufchars = 0;
vt_status[0].inputchars = 0;
vt_status[1].inputchars = 0;
vt_status[0].running = 1;
vt_status[1].running = 1;
vt_status[0].awaiting_newinput = 1;
vt_status[1].awaiting_newinput = 1;
for(;;) {
&(vt_buffer[0][vt_status[0].line][vt_status[0].bufchars]),
1);
}
do {
if(nbytes > 0) {
if(vt_buffer[0][vt_status[0].line][vt_status[0].bufchars] == '\n')
{
#ifdef DEBUG
printf("vt0 read: %s", vt_buffer[0][vt_status[0].line]);
#endif
if(active_vt == 0) {
write(STDOUT_FILENO, vt_buffer[0][vt_status[0].line],
vt_status[0].bufchars+1);
}
vt_buffer[0][vt_status[0].line][vt_status[0].bufchars+1] = '\0';
vt_status[0].line = (vt_status[0].line+1) % NUMLINES;
vt_status[0].total_lines_out++;
©2004 «GreetingLine»
Gary Nutt, Operating Systems 3/e
Instructor’s Solutions
vt_status[0].bufchars = 0;
}
else
vt_status[0].bufchars++;
}
nbytes = read(pipe_from_child_1[0],
&(vt_buffer[0][vt_status[0].line][vt_status[0].bufchars]), 1);
} while(nbytes > 0);
#ifdef DEBUG
printf("vt0 read: %s", vt_buffer[0][vt_status[0].line]);
#endif
val = fcntl(pipe_from_child_1[0], F_GETFL, 0);
val &= ~O_NONBLOCK;
fcntl(pipe_from_child_1[0], F_SETFL, val);
if(active_vt == 0) {
write(STDOUT_FILENO, vt_buffer[0][vt_status[0].line],
vt_status[0].bufchars);
}
vt_status[0].awaiting_newinput = 0;
} /* end awaiting new input */
if(vt_status[1].awaiting_newinput) {
#ifdef DEBUG
printf("reading vt1 output\n");
#endif
vt_status[1].bufchars = 0;
/* initial blocking read for prompt synch. if applicable */
if(promptsynch) {
nbytes = read(pipe_from_child_2[0],
&(vt_buffer[1][vt_status[1].line][vt_status[1].bufchars]),
1);
}
do {
if(nbytes > 0) {
if(vt_buffer[1][vt_status[1].line][vt_status[1].bufchars] == '\n')
{
#ifdef DEBUG
printf("vt1 read: %s", vt_buffer[1][vt_status[1].line]);
#endif
if(active_vt == 1) {
write(STDOUT_FILENO, vt_buffer[1][vt_status[1].line],
vt_status[1].bufchars+1);
}
vt_buffer[1][vt_status[1].line][vt_status[1].bufchars+1] = '\0';
vt_status[1].line = (vt_status[1].line+1) % NUMLINES;
vt_status[1].total_lines_out++;
vt_status[1].bufchars = 0;
}
else
vt_status[1].bufchars++;
}
nbytes = read(pipe_from_child_2[0],
&(vt_buffer[1][vt_status[1].line][vt_status[1].bufchars]), 1);
} while(nbytes > 0);
©2004 «GreetingLine»
Gary Nutt, Operating Systems 3/e
Instructor’s Solutions
#ifdef DEBUG
printf("vt1 read: %s", vt_buffer[1][vt_status[1].line]);
#endif
val = fcntl(pipe_from_child_2[0], F_GETFL, 0);
val &= ~O_NONBLOCK;
fcntl(pipe_from_child_2[0], F_SETFL, val);
if(active_vt == 1) {
write(STDOUT_FILENO, vt_buffer[1][vt_status[1].line],
vt_status[1].bufchars);
}
vt_status[1].awaiting_newinput = 0;
} /* end awaiting input */
if(c == '\e') {
c = getchar();
if(c == 'q')
vt_abort();
else if(c == 'c') {
if(vt_status[0].running && vt_status[1].running)
active_vt = (active_vt+1) % NUM_VTS;
#ifdef DEBUG
printf("active_vt = %ld\n", active_vt);
#endif
/* Write out active VT screen buffer to update display for
switch */
switch(active_vt) {
case 0:
#ifdef DEBUG
printf("writing out %ld vt lines\n",
vt_status[0].total_lines_out);
#endif
if(vt_status[0].total_lines_out > NUMLINES) {
j = (vt_status[0].line + 1) % NUMLINES;
lastline = NUMLINES - 1;
}
else {
j = 0;
lastline = vt_status[0].total_lines_out;
}
for(i=0;i<=lastline;i++) {
write(STDOUT_FILENO, vt_buffer[0][j],
strlen(vt_buffer[0][j]));
j = (j + 1) % NUMLINES;
}
write(STDOUT_FILENO, vt_input_buffer[0],
vt_status[0].inputchars);
break;
case 1:
#ifdef DEBUG
printf("writing out %ld vt lines\n",
vt_status[1].total_lines_out);
#endif
if(vt_status[1].total_lines_out > NUMLINES) {
j = (vt_status[1].line + 1) % NUMLINES;
lastline = NUMLINES - 1;
}
else {
j = 0;
lastline = vt_status[1].total_lines_out;
}
©2004 «GreetingLine»
Gary Nutt, Operating Systems 3/e
Instructor’s Solutions
for(i=0;i<=lastline;i++) {
write(STDOUT_FILENO, vt_buffer[1][j],
strlen(vt_buffer[1][j]));
j = (j + 1) % NUMLINES;
}
write(STDOUT_FILENO, vt_input_buffer[1],
vt_status[1].inputchars);
break;
default:
write(STDERR_FILENO, "switch to unknown vt\n", 21);
}
}
} /* end if esc-c vt switch command */
switch(active_vt) {
case 0:
vt_input_buffer[0][vt_status[0].inputchars] = c;
vt_status[0].inputchars++;
if(c == '\n') {
vt_input_buffer[0][vt_status[0].inputchars] = '\0';
strcat(vt_buffer[0][vt_status[0].line],
vt_input_buffer[0]);
#ifdef DEBUG
printf("vt0 written: %s", vt_input_buffer[0]);
#endif
write(pipe_to_child_1[1], vt_input_buffer[0],
vt_status[0].inputchars);
vt_status[0].inputchars = 0;
#ifdef DEBUG
printf("vt0 buffer line: %s",
vt_buffer[0][vt_status[0].line]);
#endif
vt_status[0].line = (vt_status[0].line+1) % NUMLINES;
vt_status[0].total_lines_out++;
vt_status[0].bufchars = 0;
do {
/* initial blocking read here assumes command results in
some
newline terminated output */
#ifdef DEBUG
printf("calling blocking read from child\n");
#endif
nbytes = read(pipe_from_child_1[0],
&(vt_buffer[0][vt_status[0].line][vt_status[0].bufchars]),
1);
#ifdef DEBUG
printf("nbytes = %ld\n", nbytes);
#endif
if(nbytes > 0) {
#ifdef DEBUG
printf("vt0 read char: %c",
vt_buffer[0][vt_status[0].line][vt_status[0].bufchars]);
#endif
if(vt_buffer[0][vt_status[0].line][vt_status[0].bufchars]
== '\n') {
#ifdef DEBUG
©2004 «GreetingLine»
Gary Nutt, Operating Systems 3/e
Instructor’s Solutions
printf("vt0 read line: %s",
vt_buffer[0][vt_status[0].line]);
#endif
write(STDOUT_FILENO, vt_buffer[0][vt_status[0].line],
vt_status[0].bufchars+1);
vt_buffer[0][vt_status[0].line][vt_status[0].bufchars+1] = '\0';
vt_status[0].line = (vt_status[0].line+1) % NUMLINES;
vt_status[0].total_lines_out++;
vt_status[0].bufchars = 0;
}
else {
vt_status[0].bufchars++;
}
} /* end if bytes > 0 */
} while(nbytes > 0);
if(vt_status[0].bufchars > 0) {
vt_buffer[0][vt_status[0].line][vt_status[0].bufchars] ==
'\0';
write(STDOUT_FILENO, vt_buffer[0][vt_status[0].line],
vt_status[0].bufchars);
vt_status[0].bufchars = 0;
}
else if(promptsynch) /* prompt not retrieved here */
vt_status[0].awaiting_newinput = 1;
}
break;
case 1:
vt_input_buffer[1][vt_status[1].inputchars] = c;
vt_status[1].inputchars++;
if(c == '\n') {
vt_input_buffer[1][vt_status[1].inputchars] = '\0';
strcat(vt_buffer[1][vt_status[1].line],
vt_input_buffer[1]);
#ifdef DEBUG
printf("vt1 written: %s", vt_input_buffer[1]);
#endif
write(pipe_to_child_2[1], vt_input_buffer[1],
vt_status[1].inputchars);
vt_status[1].inputchars = 0;
#ifdef DEBUG
printf("vt1 buffer line: %s",
vt_buffer[1][vt_status[1].line]);
#endif
vt_status[1].line = (vt_status[1].line+1) % NUMLINES;
vt_status[1].total_lines_out++;
vt_status[1].bufchars = 0;
do {
/* initial blocking read here assumes command results
©2004 «GreetingLine»
Gary Nutt, Operating Systems 3/e
Instructor’s Solutions
in some output */
#ifdef DEBUG
printf("calling blocking read from child\n");
#endif
nbytes = read(pipe_from_child_2[0],
&(vt_buffer[1][vt_status[1].line][vt_status[1].bufchars]),
1);
#ifdef DEBUG
printf("nbytes = %ld\n", nbytes);
#endif
if(nbytes > 0) {
#ifdef DEBUG
printf("vt1 read char: %c",
vt_buffer[1][vt_status[1].line][vt_status[1].bufchars]);
#endif
if(vt_buffer[1][vt_status[1].line][vt_status[1].bufchars]
== '\n') {
#ifdef DEBUG
printf("vt1 read: %s",
vt_buffer[1][vt_status[1].line]);
#endif
write(STDOUT_FILENO, vt_buffer[1][vt_status[1].line],
vt_status[1].bufchars+1);
vt_buffer[1][vt_status[1].line][vt_status[1].bufchars+1] = '\0';
vt_status[1].line = (vt_status[1].line+1) % NUMLINES;
vt_status[1].total_lines_out++;
vt_status[1].bufchars = 0;
}
else {
vt_status[1].bufchars++;
}
}
} while(nbytes > 0);
if(vt_status[1].bufchars > 0) {
vt_buffer[1][vt_status[1].line][vt_status[1].bufchars] ==
'\0';
write(STDOUT_FILENO, vt_buffer[1][vt_status[1].line],
vt_status[1].bufchars);
vt_status[1].bufchars = 0;
}
else if(promptsynch) /* prompt not retrieved here */
vt_status[1].awaiting_newinput = 1;
}
break;
default:
write(STDERR_FILENO, "input to unknown virtual terminal\n",
34);
©2004 «GreetingLine»
Gary Nutt, Operating Systems 3/e
Instructor’s Solutions
} /* end switch active vt */
} /* end else if vt input */
} /* end for loop */
} /* end else parent code after second fork -- the vt manager process
*/
} /* end else parent code after first fork */
©2004 «GreetingLine»
Another random document with
no related content on Scribd:
The Project Gutenberg eBook of Ending the
depression through planned obsolescence
This ebook is for the use of anyone anywhere in the United States
and most other parts of the world at no cost and with almost no
restrictions whatsoever. You may copy it, give it away or re-use it
under the terms of the Project Gutenberg License included with this
ebook or online at www.gutenberg.org. If you are not located in the
United States, you will have to check the laws of the country where
you are located before using this eBook.
Language: English
BY
Bernard London
Ending the Depression
through
Planned Obsolescence
BY
Bernard London