• web pages for usp and its programs
  • GNU make document
  • note of activation record
  • exercise 1: Compiling C programs
    • Your have to write four files, a makefile, two c programs and a c header file. (Refer to A.3)
    • The mylib.c should implement a function named reverse() which will reverse the input string in place. Its prototype is put in myinc.h and the prototype is:
      void reverse(char *s);
    • The main() in my.c should call the reverse() on each argument and print them out.
    • For example:
             $ make
             gcc    -c -o my.o my.c
             gcc    -c -o mylib.o mylib.c
             gcc -o my my.o mylib.o
             $
             $ ./my Klim is milK
             milK
             si
             Klim
             $ 
             
    • Due: 2018/Mar/14, 00:05
      You have to put your files under ~/usp-1062/exer1.
    • For your reference, a program which shows the arguments is provided.
  • exercise 2: probing argv[] and environ[]
    • Write a program which prints the values of argc, argv[], and environ[]. Also their addresses are printed. Based on the printed information, you can figure out the memory layout of argc, argv[], and environ[].
    • For example:
            $ gcc ex2-argv-env.c 
            $ env -i A=99 B=101 ./a.out "Klim is milk" is wrong
            argc is 4
            argv[0]: ./a.out
            argv[1]: Klim is milk
            argv[2]: is
            argv[3]: wrong
            environ[0]: A=99
            environ[1]: B=101
            
            argc      is at 0x7fff1c6f8fbc
            argv      is at 0x7fff1c6f8fb0
            environ   is at 0x600d98
            argv[]    is at 0x7fff1c6f90b8
            environ[] is at 0x7fff1c6f90e0
            value of argv[ 0] is 0x7fff1c6fafc7
            value of argv[ 1] is 0x7fff1c6fafcf
            value of argv[ 2] is 0x7fff1c6fafdc
            value of argv[ 3] is 0x7fff1c6fafdf
            value of env [ 0] is 0x7fff1c6fafe5
            value of env [ 1] is 0x7fff1c6fafea
            $ 
          
    • deadline: 2018/Mar/21, 00:05
    • Put your files under ~/usp-1062/exer2
  • exercise 3: creating processes with fork()
    • Write a program which will create a process tree.
    • Each process will print a line to show its pid and ppid.
    • Use wait() to ensure the lines be printed in post-order.
          $ echo $$                       # the pid of the shell
          17351
          $ ./a.out     
          I'm 17486, my parent is 17351   # just the initial a.out 
          $ ./a.out 1 1 1
          I'm 17492, my parent is 17491   # create a chain
          I'm 17491, my parent is 17490
          I'm 17490, my parent is 17489
          I'm 17489, my parent is 17351
          $ ./a.out 1 1 2                     17499
          I'm 17502, my parent is 17501         |
          I'm 17503, my parent is 17501       17500
          I'm 17501, my parent is 17500         |
          I'm 17500, my parent is 17499       17501
          I'm 17499, my parent is 17351        / \
          $ ./a.out 1 1 2 2                17502 17503     17516
          I'm 17519, my parent is 17518                      |
          I'm 17521, my parent is 17520                    17517
          I'm 17522, my parent is 17520                      |
          I'm 17520, my parent is 17518                    17518
          I'm 17518, my parent is 17517                     / \
          I'm 17517, my parent is 17516                 17519  17520
          I'm 17516, my parent is 17351                          / \
          $                                                  17521 17522
          
    • deadline: 2018/Mar/28, 00:05
    • Put your files under ~/usp-1062/exer3
  • exercise 4: practicing wait()
    • Use the code in exer3 to create a process tree.
    • The internal node should wait for all children. For each waited child, if it is terminated by a signal, the parent will show the signal number, or if it is exited, the parent will show the exit value. In either case, a number is gained from the child. Those numbers from children are summed and the sum is used as the argument of exit(). This is to say the sum is the return value of this process. Refer to example 3.22 for the usage of wait(). The pseudo code is as follows.
               for each argument do 
                 n = the value of the argument
             
                 loop n-1 times
                   fork();
                   if child then goto outer;
                 end loop
             
                 fork()
                 if parent then break;
               end for-loop
             
              outer:
               fprintf(stderr, "I'm %d, my parent is %d\n", getpid(), getppid());
             
               if leaf then 
                 while (1) pause();
               else
                 sum = 0
                 loop wait for each child
                   n = exit value or signal number
                   sum += n
                 end loop
                 exit(sum)
               endif
            
    • To test your program, you have to open another window through which you can kill a process with the command `kill'.
      For example, to kill a process which pid is 12011 with signal 15, you can type 'kill -15 12011'.
    • For example
             $ gcc ex4-wait.c 
             $ echo $$
             15000
             $ ./a.out 2 3 2                             15496
             I'm 15496, my parent is 15000               /    \
             I'm 15498, my parent is 15496          15497      15498
             I'm 15497, my parent is 15496                  /    |    \
             I'm 15501, my parent is 15498               15499 15500 15501
             I'm 15500, my parent is 15498                           /   \
             I'm 15499, my parent is 15498                        15502  15503
             I'm 15503, my parent is 15501
             I'm 15502, my parent is 15501          +----- another window ----+
             child 15499 signaled with signal 1     |   $ kill  -1 15499      |
             child 15500 signaled with signal 9     |   $ kill  -9 15500      |
             child 15502 signaled with signal 15    |   $ kill -15 15502      |
             child 15503 signaled with signal 1     |   $ kill  -1 15503      |
             child 15501 exited with value 16       |                         |
             child 15498 exited with value 26       |                         |
             child 15497 signaled with signal 1     |   $ kill  -1 15497      |
             $ echo $?                              +-------------------------+
             27
             $ 
            
    • deadline: 2018/Apr/04, 00:05
    • Put your files under ~/usp-1062/exer4
  • exercise 5: simulating `rev'
    • Refer to manual page of 'rev'.
      Your `rev' should be capable of being invoked as
       
            $ ./myrev file1 file2 file3 ..    # reading from files, files1..
            $ ./myrev                         # reading from stdin.
            
    • Deadline: 2018 Apr 11 00:05am
    • Put your file(s) under ~/usp-1062/exer5
    • Only read(), write() and the functions defined in text are allowed.
  • exercise 6: practicing pipe()
    • Refer to the description of exercise 2 (usp-982) for explanation of code .
    • Use the code shown above to build a process tree, but two pipes are created between a parent and each one of its children. One pipe is for parent's sending to child, the other is for child's sending to the parent.
    • After created, each process will do something as follows.
             loop
                 if root then  ch = get a char from stdin
                         else  ch = get a char from parent
             
               if ch='o' or ch='q' then   /* post-order or quit */
                   for each child  do
                       send ch to child
                       get ack from child 
                   show this process's info
               else if ch='p'             /* pre-order */
                   show this process's info
                   for each child  do
                       send ch to child
                       get ack from child 
      
               if not root then send ack to parent
               if ch='q' then break
             forever
            
    • For example:
             $ ./a.out ddudduduuu abcde
             p
             I'm a, my pid=29845, and my ppid=28861
             I'm b, my pid=29846, and my ppid=29845
             I'm c, my pid=29847, and my ppid=29845
             I'm d, my pid=29848, and my ppid=29847
             I'm e, my pid=29849, and my ppid=29847
             o
             I'm b, my pid=29846, and my ppid=29845
             I'm d, my pid=29848, and my ppid=29847
             I'm e, my pid=29849, and my ppid=29847
             I'm c, my pid=29847, and my ppid=29845
             I'm a, my pid=29845, and my ppid=28861
             q
             I'm b, my pid=29846, and my ppid=29845
             I'm d, my pid=29848, and my ppid=29847
             I'm e, my pid=29849, and my ppid=29847
             I'm c, my pid=29847, and my ppid=29845
             I'm a, my pid=29845, and my ppid=28861
             $ 
            
    • Deadline: 2018 May 02 00:05am
    • Put your file(s) under ~/usp-1062/exer6
  • exercise 7: practicing select() or poll()
    • Generate a bidirectional ring. Refer to program 7.1. The argv[1] specifies the number of processes.
    • After the ring is setup, the root process then does
                loop
                  read from stdin 
                  if got 'f' then 
                    send 0 1 to the clockwise next process
                    read two numbers from clockwise previous process
                    write the first out (This is the n-th fibonacci number)
                  if got 'p' then 
                    write a token to the anti-clockwise next process
                    read a token from anti-clockwise previous process
                    show pid
                  if got 'q' then 
                    write a token to the anti-clockwise next process
                    read a token from anti-clockwise previous process
                    exit
                end loop
             
      Each child does
               loop
                 monitor two inputs simultaneously 
                 (one clockwise and another anti-clockwise)
                 if clockwise input is ready then 
                   read two numbers, a and b, from clockwise previous process
                   show them
                   write b (a+b) to clockwise next process
                 if anti-clockwise input is ready then
                   read a token from anti-clockwise previous process
                   if the token is for print then 
                     show pid
                   else
                     exit
               end loop
             
    • For example:
              $ ./a.out 4
              p
              I am 28206
              I am 28205
              I am 28204
              I am 28203, the root
              f
              I am 28204, I got   0   1
              I am 28205, I got   1   1
              I am 28206, I got   1   2
              I am root.  I got   2   3. Fib(4) = 2
              q
              $ 
             
    • Due: 2018/May/23, 00:05
  • exercise 8: practicing sigaction()
    • Do the same thing as exercise 7. But instead of initiating operating from the root process, the 'p' or 'f' operation is initiated from any process when it receives a signal.
    • First each process will show its pid when created.
    • Then send signals from another window. In following examples SIGUSR1 is a signal for doing 'fibonacci', SIGUSR2 for printing pid, and SIGINT for exiting.
              $ ./a.out 4
              I am 437            <----- At first, each procoess shows its pid.
              I am 438
              I am 439
              I am 440
              I am  438, I got   0   1     <----- kill -USR1 437
              I am  439, I got   1   1
              I am  440, I got   1   2
              I am  437. I got   2   3
              I am  437, I got   0   1     <----- kill -USR1 440
              I am  438, I got   1   1
              I am  439, I got   1   2
              I am  440. I got   2   3
              I am  439                    <----- kill -USR2 440
              I am  438
              I am  437
              I am  440.                   <----- kill -INT 440
              $ 
             
    • To wait two files and signals concurrently, use ppoll() or pselect().
    • Due: 2018/June/06, 00:05
  • exercise 8: practicing sigaction()
    • Do the same thing as exercise 7. But instead of initiating operating from the root process, the 'p' or 'f' operation is initiated from any process when it receives a signal.
    • First each process will show its pid when created.
    • Then send signals from another window. In following examples SIGUSR1 is a signal for doing 'fibonacci', SIGUSR2 for printing pid, and SIGINT for exiting.
              $ ./a.out 4
              I am 437            <----- At first, each process shows its pid.
              I am 438
              I am 439
              I am 440
              I am  438, I got   0   1     <----- kill -USR1 437
              I am  439, I got   1   1
              I am  440, I got   1   2
              I am  437. I got   2   3
              I am  437, I got   0   1     <----- kill -USR1 440
              I am  438, I got   1   1
              I am  439, I got   1   2
              I am  440. I got   2   3
              I am  439                    <----- kill -USR2 440
              I am  438
              I am  437
              I am  440.                   <----- kill -INT 440
              $ 
             
    • To wait two files and signals concurrently, use ppoll() or pselect().
    • Due: 2018/June/06, 00:05
  • exercise 9: practicing pthread
    • The main thread first creates 6 threads. Each thread will generate 100 pairs of integers which are between 0..48.
    • The main thread then join them. So it get 600 pairs.
    • Using these pairs as pairs of index to an array which is initialized as 1,2,3,.....49, the main thread can swap the array 600 times. And Select the first six as the result. For example,
             $ gcc ex9-thread-ball.c -lpthread
             $ ./a.out 
             The balls are   9  6 36 17 40 32
             $ ./a.out 
             The balls are  18  6 21 22 25 12
             $ ./a.out 
             The balls are  14 11 24  8 38 12
             $ ./a.out 
             The balls are  16 35 22 28 30  8
             $
             
    • You should use thread-safe random functions, such as erand48(), or nrand48().
    • Each thread should use different seed.
    • Due: 2018/June/20, 00:05