Review the pipe manpages in the /examples/b/man directory. Then copy these files into your directory:
1. Log on to Odin
2. Do Not run a umask command
Run this instead...
$ /home/fac/gordon/p/3600/lab-setup.sh
3. Copy the lab files...
$ cd 3600/b
$ cp /home/fac/gordon/public_html/3600/examples/b/*.c .
$ cp /home/fac/gordon/public_html/3600/examples/b/Makefile .
You may copy all the sample file if you like.
dotprod.c uses four threads to compute
the dot product of two integer vectors. Your job is to modify the program to
incorporate a pipe. You will
use the pipe to communicate between the threads and a forked child.$ cp dotprod.c mylab11.cFix your Makefile to build mylab11.c
You are going to add a fork to your code. Open the pipe before the fork. The child's job is to read from the pipe, blocking until something is sent down the pipe. Meanwhile, the parent spawns the threads. Each thread writes its result to the pipe. The child reads the results from the pipe, sums the results and displays the result on the screen. If all goes well you will see the sum of 1+2+3+ ... +494+495+496.
A note about pipes. They are very low level. Pipes use the write command to stuff data into the pipe and the read command to grab data from the pipe. It is up to you to know what format the stuff that you read and write is expected to be in. If you send integers you need to know an int is four bytes. Then you can do this:
int out = 25; write(mypipe, &out, 4); int in; read(mypipe, &in, 4);If you are careful you will need to modify very little of the dotprod.c code. Create a global set of file descriptors for the pipe (one is for the incoming end and one for the outgoing end):
int pipefd[2]; /* give your file descriptors a name you like */ A child process inherits file descriptors from the parent. A pipe has 2 file descriptors, the read end and the write end.Before the fork open the pipe:
pipe(pipefd);Insert the code to read and write in the correct spots in parent and child. The threads will write to the parent's end of the pipe. Follow this diagram:
---------------- --------------- PARENT PROCESS CHILD PROCESS ---------------- --------------- close(pipefd[0]) close(pipefd[1]) [Outgoing End] /-------------------\ [Incoming End] write(pipefd[1]) ==> >> data >> ==> read(pipefd[0]) close(pipefd[1]) >> EOF >> \-------------------/ Use pipetest.c as an example.The outgoing end pipefd[1] behaves like stdout; i.e., the threads write to it. The incoming end pipefd[0] behaves like stdin; i.e., the child reads from it.
Note: pipes are IPC only - you should not use a pipe to communicate between threads of the same process.
Clarification of this lab... 1. You are given a program that works. Portions of a dot-product are summed inside of threads. The summing will no longer be done in the threads. Comment out this line in your thread function: /* dotstr.total += localsum; */ Do not remove the line of code. Comment it out. <----- Write localsum to your pipe, instead. There is no longer a need for dotstr.total in the program. You must comment it out... typedef struct { int *a; int *b; /* int total; */ int veclen; } Dotdata; Do not remove the line, rather comment it out. <----- Declare a local variable within the scope of the child process to sum the dot-product components. Create a variable name that helps to self-document your program, and a name that you think will be unique among all the lab programs written by students in our class. 2. The parent process will create and control the threads, but will no longer display the final dot-product. Comment this line out: /* printf ("the dot product sum: %d\n", dotstr.total); */ Instead, write a line of code in your child process that will display the final dot-product value. 3. The child process will now do the summing of the dot-product components. It is accomplished by reading all the component values that come out of the read-end of the pipe. The child process will display the dot-product to the screen. Notes: The test run using strace is not usually performed by your instructor during grading of an assignment. The Linux manpage for pipe(2) is a great source for this lab.
Sample runs:
$ ./lab11 Child process sum from pipe: 123256 Child's exit code: 0
$ strace -f -e trace=pipe,read,write,close ./lab11 2>out $ cat out close(3) = 0 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0> \0\1\0\0\0@\\\0\0\0\0\0\0"..., 832) = 832 close(3) = 0 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0> \0\1\0\0\0\300\357\1\0\0\0\0\0"..., 832) = 832 close(3) = 0 pipe([3, 4]) = 0 Process 1691 attached [pid 1688] close(3) = 0 Process 1692 attached Process 1693 attached Process 1694 attached Process 1695 attached [pid 1692] write(4, "\272\23\0\0", 4) = 4 [pid 1692] close(3) = 0 [pid 1692] read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0> \0\1\0\0\0p.\0\0\0\0\0\0"..., 832) = 832 [pid 1692] close(3) = 0 Process 1692 detached [pid 1691] close(4) = 0 [pid 1691] read(3, "\272\23\0\0", 4) = 4 [pid 1691] read(3, <unfinished ...> [pid 1694] write(4, "\332a\0\0", 4) = 4 [pid 1693] write(4, "\312:\0\0", 4) = 4 Process 1694 detached [pid 1691] <... read resumed> "\332a\0\0", 4) = 4 [pid 1691] read(3, "\312:\0\0", 4) = 4 Process 1693 detached [pid 1691] read(3, <unfinished ...> [pid 1695] write(4, "\352\210\0\0", 4) = 4 [pid 1691] <... read resumed> "\352\210\0\0", 4) = 4 [pid 1691] read(3, Process 1695 detached <unfinished ...> [pid 1688] close(4 <unfinished ...> [pid 1691] <... read resumed> "", 4) = 0 [pid 1688] <... close resumed> ) = 0 [pid 1691] write(1, "Child process sum from pipe: 119316\n", 29) = 29 [pid 1691] close(3) = 0 Process 1691 detached --- SIGCHLD (Child exited) @ 0 (0) --- write(1, "Child's exit code: 0\n", 21) = 21
Files due at 9:50am...
3600/b/mylab11.c 3600/b/Makefile