CS 241 Section Week #3 (09/11/08)

Download as ppt, pdf, or txt
Download as ppt, pdf, or txt
You are on page 1of 36

CS 241 Section Week #3

(09/11/08)
Topics This Section

 Review of HW1
 Lecture review
 MP1
 Processes
Review of HW1
Function (call by value vs call by reference)

5.
void increment(int x) {
x++;
}
...

for(x=0;x<10;increment(x)) {
printf("x=%d\n",x);
}

the x in the increment


function is local to it;
incrementing x there doesn't
change the value outside the
function.
Memory

10.
char *s;
s=(char *) malloc (100);
s="hello";
free(s);

s points to the string in the


string constant table and the
allocated block is orphaned.
Hence a free() will cause
segmentation fault.
Dynamic allocation of two-dimensional arrays

int **array;
int i,j,10;
array = malloc(10*sizeof(int*));
for(i=0;i<10;i++)
for(j=0;j<10;j++)
array[i][j] = i*j;

While the first layer of array is


allocated, the second layer is
not. Each array[i] needs to be
allocated to be used as an
array. Therefore, add a malloc
statement inside the loop
Precedence

27.
char *str,*p;
...
p=str;
while(*p!=0) {
*p++;
p++;
}

This code attempts to increment every


value in a string. However, ++ binds more
closely to p than *. Therefore "*p++" is
the same as "*(p++)". This program will
not change str at all.
Macros

30.
#define cube(x) x*x*x
#define double(x) x+x
x = 3;
y = cube(x + 1);
z = 5 * double(x);

The compiler simply replaces a macro reference


with expanded text according to the macro's
definition. Hence the compiler expands
cube(x+1) as: x + 1*x + 1*x + 1. You can avoid
many problems with macros by following a
simple rule: Put parentheses (or other explicit
delimiters) around the macro text and around
each macro argument within the macro text.
String manipulation functions
 Read some “source” string(s), possibly write to some
“destination” location
char *strcpy(char *dst, char const *src);
char *strcat (char *dst, char const *src);
 Programmer’s responsibility to ensure that:
 destination region large enough to hold result
 source, destination regions don’t overlap
 “undefined” behavior in this case –
according to C spec, anything could happen!
Assuming that the implementation of strcpy
char m[10] = ″dog″; starts copying left-to-right without checking for
strcpy(m+1, m); the presence of a terminating NUL first, what
will happen?
Lecture Review
Environment variables
 Setting an environment variable
 VAR=/home/lchen2/doc
 export PATH=$PATH:/home/lchen2/exec
 SYSTEMNAME=`uname –n`
 Using environment variables
 echo $VAR
 cd $HOME (same as cd)
 echo “You are running on $SYSTEMNAME”
Some important environment variables

 HOME
 Your home directory (can often be abbreviated as “~”)
 TERM
 The type of terminal you are running
 PWD
 Current working directory
 PATH
 List of directories to search for commands
PATH environment variable
 Controls where commands are found
 PATH is a list of directory pathnames separated by colons(:)
 If a command does not begin with a slash, the shell tries
finding the command in each directory in PATH. The first
match is the command that is run.
 Same PATH
 PATH=/bin:/usr/bin:/usr/X11R6/bin:/usr/local/bin
 Some people include “.” in PATH
 It may be a security problem
extern
 To indicate the existence of, and the type of, a global
variable
 To inform the compiler about variables declared outside of
the current scope
 Will not have any space allocated for them
 To allow data to span the scope of multiple files
MP1
MP1
 Part1
 Write your code between the markers we provide in the
code. Don't move the comments into one line.
 Recall that a char value can be thought of as either a
character or a small integer
 ‘a’ + 1 is ‘b’
 ‘Z’ - ‘A’ is 25
 Part2
 2e we accept both
 (s1 & s2) & s3
 (s1 & s2) (s2&s3)
Processes
Process Creation with fork()

 fork() creates a new process:


env env
stack fork() stack
free free
heap heap
static creates static
code code
Parent Child

 The new (child) process is identical to the


old (parent) process, except…
Differences between parent and child

 Process ID (getpid())
 Parent ID (getppid())
 Return value of fork()
 In parent, fork() returns child pid
 In child, fork() returns 0
fork() Example 1
 What does this do?

 fprintf(stdout,”%d\n”,fork());
fork() example 2

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char** argv) {


pid_t child_pid = fork();
if (child_pid < 0) { // error code
perror(“Fork Failed”);
return –1;
}
fprintf(stdout, “I am process %d\n”,getpid());
if (child_pid == 0) { // child code
fprintf(stdout,”I’m the child process.\n”);
} else { // parent code
fprintf(stdout,”I’m the parent of child process %d.\n”, child_pid);
}
return 0;

}
Example 2 cont’d
 This exits too quickly; let’s slow it down:

if (child_pid == 0) { // child code


sleep(15);
fprintf(stdout,”I’m the child process.\n”);
} else { // parent code
sleep(20);
fprintf(stdout,”I’m the parent of child process %d.\n”,
child_pid);
}
Example 2 cont’d
 In a second window, run ps –a, and look for the pids from the
program output.
 Periodically run ps –a again, as the program in the first window
executes.
 What happens when the program runs?
 What happens when the child finishes?
 What happens when the parent finishes?
 What happens when you switch the parent and child sleep
statements?
Process Termination
 Normal exit (voluntary)
 End of main()
 Error exit (voluntary)
 exit(2)
 Fatal error (involuntary)
 Divide by 0, core dump / seg fault
 Killed by another process (involuntary)
 Kill procID, end task
 How can a parent know when its children are done?
Solution: wait(…)

 wait() allows a parent to wait for its child process,


and save its return value
 pid= wait(&status , options);
 pid= waitpid(pid , &status ,options);

 wait() waits for any child; waitpid() waits for a


specific child.
wait cont’d
 wait() blocks until child finishes
 wait() does not block if the option WNOHANG is included.
When would we want to use this?
 The child’s return value is stored in *status
wait(...) macros
 WIFEXITED(status) is true iff the process terminated
normally.

 WEXITSTATUS(status) gives the last 8 bits of the


process’s return value (assuming normal exit)
Example 3: wait

#include <sys/wait.h>
…

…

// add this to parent code


if (waitpid(child_pid, &result, 0) == -1) {
perror(”Wait failed”);

return -1;

}

if( WIFEXITED(result)) {
fprintf(stdout, ”child %d returned %d\n”,
child_pid, WEXITSTATUS(result));
exec

 exec replaces the current process image(code, variables, etc.)


with that of a new program:

Before After
env env*
stack exec
free
New
heap
Program
static
code
* The program may
choose to change the
environment
exec variations
 There are 6 different ways of calling exec. Which one
to use depends on three conditions:
1. How arguments are passed
2. How the path is specified
3. Whether a new environment is used
exec variations: passing parameters

 exec can have parameters passed to it two different ways:


 List of parameters:
 execl(“/usr/bin/ls”, ”ls”, ”-l”, NULL);
 Argument Vector (like argv):
 execv(argv[1],argv+1);

 Q: When would you use execl?


 When would you use execv?
exec variations: command path

 Adding a “p” to an exec call tells the system to look for


the command in the environment’s path.
 Compare:
 execl(“/usr/bin/ls”, ”ls”, ”-l”, NULL);
 execlp(“ls”, ”ls”, ”-l”, NULL);
 The difference is similar for execv and execvp.
exec variations (cont’d)

 By default, the new program inherits the old program’s


environment. Adding an “e” to the exec call allows the
new program to run with a new environment
**environ

 execve and execle allow the user to specify the


environment. The others inherit the old environment.
fork + exec
 If exec succeeds, it does not return, as it overwrites the
program.
 No checking return values, executing multiple commands,
monitoring results, etc.
 Solution: fork a new process, and have the child run exec
Example 5: exec

#include <unistd.h>
#include <stdio.h>

int main(int argc, char** argv) {


child_pid = fork();
if (child_pid < 0) {
perror(“Fork failed”);
return –1;
} else if (child_pid == 0) {
if (execvp(argv[1], argv+1) < 0) {
fprintf(stderr,”Failed to execute %s!\n”, argv[1]);
perror(”child exec:”);
return -1;
}

}

// What belongs here?


...

return 0;
}

You might also like