• 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 sum_str() which prototype is put in mylib.h and the prototype is:
      int sum_str(char *s);
    • The main() in main.c should call the sum_str() on each argument, figure out the sum, and print out the sum.
    • For example:
            $ ls
            Makefile  main.c  mylib.c  mylib.h
            $ make 
            gcc    -c -o main.o main.c
            gcc    -c -o mylib.o mylib.c
            gcc -o sum main.o mylib.o
            $ touch mylib.h
            $ make
            gcc    -c -o main.o main.c
            gcc    -c -o mylib.o mylib.c
            gcc -o sum main.o mylib.o
            $ touch mylib.c
            $ make
            gcc    -c -o mylib.o mylib.c
            gcc -o sum main.o mylib.o
            $ touch main.c
            $ make
            gcc    -c -o main.o main.c
            gcc -o sum main.o mylib.o
            $ rm sum
            $ make
            gcc -o sum main.o mylib.o
            $ 
            $ ./sum 1 2 3
            The sum of arguments is 6
            $ ./sum 1 2 3 "1 2 3"
            The sum of arguments is 12
            $ ./sum 1 2 3 "1 2 3" "1000 1"
            The sum of arguments is 1013
            $ 
          
    • deadline: 2016/Mar/4, 00:05
    • Put your files under ~/usp-1042/exer1
  • 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, one can figure out the memory layout of argc, argv[], and environ[].
    • For example:
            $ env -i klim=milk milk=coffee ./usp-ex2 one apple a day
            argc is 5
            argv[0]: ./usp-ex2
            argv[1]: one
            argv[2]: apple
            argv[3]: a
            argv[4]: day
            environ[0]: klim=milk
            environ[1]: milk=coffee
            
            argc      is at 0x7fff9ead9dfc
            argv      is at 0x7fff9ead9df0
            environ   is at 0x600d98
            argv[]    is at 0x7fff9ead9ef8
            environ[] is at 0x7fff9ead9f28
            value of argv[ 0] is 0x7fff9eadafbe
            value of argv[ 1] is 0x7fff9eadafc8
            value of argv[ 2] is 0x7fff9eadafcc
            value of argv[ 3] is 0x7fff9eadafd2
            value of argv[ 4] is 0x7fff9eadafd4
            value of env [ 0] is 0x7fff9eadafd8
            value of env [ 1] is 0x7fff9eadafe2
            $ 
          
    • deadline: 2016/Mar/11, 00:05
    • Put your files under ~/usp-1042/exer2
  • exercise 3: creating processes with fork()
    • Write a program which will create a process tree.
    • The tree is a fully binary tree and is left skewed where argv[1] denotes the number of internal nodes.
    • For example:
            $ ./a.out 3
            I am internal 31512. My left and right are 31513 and 31514.
            I am external 31514. My parent is 31512.
            I am internal 31513. My left and right are 31515 and 31516.
            I am external 31516. My parent is 31513.
            I am internal 31515. My left and right are 31517 and 31518.
            I am external 31518. My parent is 31515.
            I am external 31517. My parent is 31515.
            ^C
            $ 
          
    • To prevent the parent processes from exiting too early, put the following code into your program.
              while(1) pause();
          
    • deadline: 2016/Mar/25, 00:05
    • Put your files under ~/usp-1042/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().
    • 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
               $ ./a.out 3
               I am internal 2368. My left and right are 2369 and 2370.
               I am external 2370. My parent is 2368.
               I am internal 2369. My left and right are 2371 and 2372.
               I am external 2372. My parent is 2369.
               I am internal 2371. My left and right are 2373 and 2374.
               I am external 2374. My parent is 2371.
               I am external 2373. My parent is 2371.
               child 2373 signaled with signal 2        < ---- kill -2 2373
               child 2374 signaled with signal 3        < ---- kill -3 2374
               child 2371 exited with value 5
               child 2372 signaled with signal 1        < ---- kill -1 2372
               child 2369 exited with value 6
               child 2370 signaled with signal 5        < ---- kill -5 2370
               $ echo $?
               11
               $ 
            
    • deadline: 2016/Apr/01, 00:05
    • Put your files under ~/usp-1042/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: 2016 Apr 8 00:05am
    • Put your file(s) under ~/usp-1042/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.
    • Each process will print two lines. The first line is printed in preorder and the second in post-order.
    • For example:
            $ ./a.out ddduduuduu abcde
            I'm a, my pid=27828, and my ppid=27682
            I'm b, my pid=27829, and my ppid=27828
            I'm c, my pid=27830, and my ppid=27829
            I'm d, my pid=27832, and my ppid=27829
            I'm e, my pid=27831, and my ppid=27828
            I'm c, my pid=27830, and my ppid=27829
            I'm d, my pid=27832, and my ppid=27829
            I'm b, my pid=27829, and my ppid=27828
            I'm e, my pid=27831, and my ppid=27828
            I'm a, my pid=27828, and my ppid=27682
            $ 
            
    • Deadline: 2016 Apr 15 00:05am
    • Put your file(s) under ~/usp-1042/exer6
  • exercise 7: practicing select() or poll()
    • Generate a bidirectional ring. Refer to program 7.1. The argv[1] specified the number of processes.
    • After the ring is setup, the root process then does
                loop
                  read from stdin 
                  if got 'l' then 
                    generate 12 random numbers between 1 to 49
                    send them to the clockwise next process
                    read 12 numbers from clockwise previous process
                    write the first six out
                  if got 'p' then 
                    write a token to the anti-clockwise next process
                    read a token from anti-clockwise previous process
                end loop
             
      Each child does
               loop
                 monitor two inputs simultaneously 
                 (one clockwise and another anti-clockwise)
                 if clockwise input is ready then 
                   read 12 numbers from clockwise previous process
                   show them
                   randomly generate a, b
                   swap a-th and b-th numbers
                   write 12 numbers to clockwise next process
                 if anti-clockwise input is ready then
                   read a token from anti-clockwise previous process
                   show the a, b (previously generated random numbers)
                   write a token to the anti-clockwise next process
               end loop
             
    • Note that the seeds used to generate random sequences should be distinct.
    • You may design a method with which all process can be terminated gracefully.
    • Due: 2016/Apr/29, 00:05
    • For example:
              $ ./a.out 6     <----- one root, five children
              l
               40  9 18 41  3 28 39 36 15  2 33 43
               40  9 33 41  3 28 39 36 15  2 18 43
               40  9 33 41 39 28  3 36 15  2 18 43
               40  9 33 41 28 39  3 36 15  2 18 43
               40  9 33  3 28 39 41 36 15  2 18 43
              The six balls: 40  9 33  3 18 39
              l
               35 14 21  7 30 27 24 38 31 26 40  2
               35 14 21  7 30 27  2 38 31 26 40 24
               35 14 21 38 30 27  2  7 31 26 40 24
               38 14 21 35 30 27  2  7 31 26 40 24
               38  2 21 35 30 27 14  7 31 26 40 24
              The six balls: 14  2 21 35 30 27
              p
              It is time to list the random numbers.
              I'am 26069 and my random numbers are  6 and  0
              I'am 26068 and my random numbers are  6 and  1
              I'am 26067 and my random numbers are  0 and  3
              I'am 26066 and my random numbers are  3 and  7
              I'am 26065 and my random numbers are  6 and 11
              q
              $ 
             
  • exercise 8: traversing directories
    • Refer to Chapter 5.8.
    • Only depth first version is required.
    • Due: 2016/May/13, 00:05
  • exercise 9: writing signal handlers
    • Create a process tree. The argument is like exercise 6.
    • Set signal handlers for each process. There are five signals to hanle. Two are used to print message in preorder. Another two are used to remove nodes. And the last one is used to acknowledge.
              $ ./a.out ddduduudduuu abdecf
              I'm a, my pid=26895, and my ppid=25582   
              I'm c, my pid=26897, and my ppid=26895
              I'm b, my pid=26896, and my ppid=26895
              I'm f, my pid=26898, and my ppid=26897
              I'm e, my pid=26900, and my ppid=26896
              I'm d, my pid=26899, and my ppid=26896
              I'm a, my pid=26895, and my ppid=25582   <---- kill -1 26895
              I'm b, my pid=26896, and my ppid=26895
              I'm d, my pid=26899, and my ppid=26896
              I'm e, my pid=26900, and my ppid=26896
              I'm c, my pid=26897, and my ppid=26895
              I'm f, my pid=26898, and my ppid=26897
              I'm b, my pid=26896, and my ppid=26895   <---- kill -1 26896
              I'm d, my pid=26899, and my ppid=26896
              I'm e, my pid=26900, and my ppid=26896
              I'm c, my pid=26897, and my ppid=26895   <---- kill -1 26897
              I'm f, my pid=26898, and my ppid=26897
              I'm c, my pid=26897, and my ppid=26895   <---- kill -3 26897; kill -1 26897
              I'm b, my pid=26896, and my ppid=26895   <---- kill -3 26896; kill -1 26896 
              I'm a, my pid=26895, and my ppid=25582   <---- kill -1 26895
              I'm b, my pid=26896, and my ppid=26895
              I'm c, my pid=26897, and my ppid=26895
              I'm a, my pid=26895, and my ppid=25582   <---- kill -3 26895; kill -1 26895
              Killed                                   <---- kill -9 26895
              $ 
             
    • Due: 2016/May/20, 00:05
  • exercise 10: asynchrous read and write
    • Refer to 8.10 but the exercise asks you to use aio_read and aio_write.
    • The main function just reads from stdin and writes to stdout while the signal handlers maintain the file copying. The scenario may be like:
      
             $ ./a.out  infile  outfile    <----- copy infile to outfile
             hello i'm klim                       with async read and async write
             hello i'm klim        <---- read stdin and echo it to stdout ...
             ...
             ...
             [Copy completed]      <------ when the copy is completed, show something 
             ..                            to screen
             ..
             ^D
             $
             
    • In order to simulate a slow device, I have modified the periodicasterisk.c in text such that it will read characters from stdin and write them to stdout in the rate of n characters per second.
      Through a fifo, this program can be used as follows.
       
             1st shell:
             $ ./periodicchars 12  < FIFO
             ....... <---- the contents of infile is shown here 
             in the rate of 12 chars per second
      
             2nd shell:
             $ ./a.out infile FIFO  <-----   the contents of infile is sent 
             hello klim                      to FIFO
             hello klim 
             .......
             
    • Due: 2016/June/03 00:05
    • Check the man page of aio_read. An additional library is required.
  • exercise 11: pthread creating and joining
    • Refer to Chapter 12.
    • The main thread creates 6 threads each of which will generate 100 numbers between 0 and 41. The main thread then joins them and collects the 600 numbers. The numbers are viewd as 300 pairs. Each pair of numbers is used to swap the elements of an array which is initialized as num[i]=i+1, i=0..41. Finally the main thread prints out the first six numbers.
    • Each thread should use different seeds and you should use thread-safe random functions, such as erand48() or nrand48().
             $ gcc ex-12.c -lpthread
             $ ./a.out 
             The balls are  29 42 35 37  5 14
             $ ./a.out 
             The balls are  12 10 15 22  9 34
             $ ./a.out 
             The balls are   6 20 28 35  2 11
             $ ./a.out 
             The balls are  39  4 22 41 17 14
             $ ./a.out 
             The balls are  39  1 20 26 42 13
             $ ./a.out 
             The balls are  11 42 28  2 26  9
             $ 
             
    • Due: 2015/06/17 00:05