Homework 2 Solutions

22C:116, Spring 1995

Herbert Hoeger

  1. Write Unix code (using the programming language of your choice, and note that you need not run it!) that is equivalent to the following pseudocode, where a, b and c are statements.

    cobegin a; b; c; coend

            var pid, stat: integer;
    
            begin
               if (fork() <> 0) then          { parent }
                  if (fork() <> 0) then begin { parent }
                     writeln('... Execute A');
                     pid := wait(stat);       { wait for a child }
                     pid := wait(stat);       { wait for the other }
                  end else begin              { second child }
                     writeln('... Execute C');
                     exit(0);
                  end;
                else begin                    { first child }
                  writeln('... Execute B');
                  exit(0);
                end;
            end.
    

  2. Write Unix code equivalent to the following pseudocode, where a, b, c, d, e, f, g, h, i and j are statements.

    begin

    end
            var pid, pid1, pid2, stat : integer;
    
            begin
               writeln('... Executing A');
               pid1 := fork();
               if (pid1 <> 0) then begin      { Parent BF }
                  writeln('... Executing B');
                  pid2 := fork();
                  if (pid2 <> 0) then begin   { Parent CD }
                     writeln('... Executing C');
                     repeat                   { wait for right child }
                        pid := wait(stat);
                        if pid = pid1 then    { wrong child! }
                           pid1 := pid2;      { prevent later wait! }
                     until pid = pid2;
                  end else begin              { Child CD }
                     writeln('... Executing D');
                     exit(0);
                  end;
                  writeln('Executing E');
                  while pid <> pid1 do        { if child CD not done }
                     pid := wait(stat);
                                   
               end else begin                 { Child BF }
                  writeln('... Executing F');
                  if (fork() <> 0) then begin { Parent GH }
                     writeln('... Executing G');
                     pid := wait(stat);       { wait for child GH }
                  end else begin		  { Child GH }
                     writeln('... Executing H');
                     exit(0);
                  end;
                  writeln('... Executing I');
                  exit(0);
               end;
               writeln('... Executing J');
            end.
    
    

    Note that the above code is a bit tricky because of the code needed to figure out which process had terminated!

  3. What, if any, are the significant differences in the pipe commands of Ultrix, HP/UX and Sunos, as documented in their respective man pages.
        Granularity:
           Ultrix: up to PIPE MAX bytes buffered before the
                   writing process is suspended. The pipe
                   can hold up to 4096 bytes.  Is PIPE MAX
                   equal to 4096?
           SunOS:  up to PIPE BUF bytes can be buffered
                   before the writing process is suspended.
                   Is this the maximum number of bytes
                   a pipe can hold?
           HP/UX:  does not say anything about this.
    
        Implementation:
           Ultrix: soket based.
           SunOS:  implemented through the file system.
           HP/UX:  does not say anything about this.
    

  4. The documentation of the possibility of deadlock in the SUNOS man page for pipes is in error. What is the error?
        The man page says that if one pipe in a cycle fills,
        a deadlock may result.  In fact, this will only block
        one process.  All must be blocked to cause a deadlock.