Reputation: 439
This is an exercise in "APUE" chapter 8(exercise 8.2, 2th edtion). The all discription is:
Recall the typical arrangement of memory in Figure 7.6. Because the stack frames corresponding to each function call are usually stored in the stack, and because after a vfork the child runs in the address space of the parent, what happens if the call to vfork is from a function other than main and the child does a return from this function after the vfork? Write a test program to verify this, and draw a picture of what’s happening.
In my program:
static void f1(void), f2(void);
int main(void) {
printf("main address: %d\n", main);
f1();
f2();
_exit(0);
}
static void f1(void) {
printf("f1 address: %d\n", f1);
pid_t pid;
if ((pid = vfork()) < 0)
err_sys("vfork error");
}
static void f2(void) {
printf("f2 address: %d\n", f2);
char buf[1000];
int i;
for (i = 0; i < sizeof(buf); ++i)
buf[i] = 0;
}
I run the program, the output is:
main address: 4196560
f1 address: 4196604
f2 address: 4196663
f1 address: 4196604
[1] 12929 segmentation fault ./a.out
I am confused about the output.
f1 address: xxx
, we call vfork(), the child process runs first. f2 address: xxx
, then child process calls _exit(0).But why print f1 address: 4196604
twice and why the address of f1 and f2 are not same?
Upvotes: 0
Views: 432
Reputation: 315
According to vfork
documentation, you should not return from current function.
vfork() differs from fork(2) in that the calling thread is suspended until the child terminates (either normally, by calling _exit(2), or abnormally, after delivery of a fatal signal), or it makes a call to execve(2). Until that point, the child shares all memory with its parent, including the stack. The child must not return from the current function or call exit(3), but may call _exit(2).
Also, please note that:
vfork() is a special case of clone(2). It is used to create new processes without copying the page tables of the parent process. It may be useful in performance-sensitive applications where a child is created which then immediately issues an execve(2).
Since vfork
does not copy the page tables from the parent, it makes a lot of sense not to return from current function. When the child exits it will mess up the stack frame from the parent.
You can also view the following answer
Upvotes: 0
Reputation: 90621
I'm not sure what you mean by "the statck frame of f1 was changed by f2".
The code in f2()
is likely to segmentation fault in any case, regardless of vfork()
. buf
is uninitialized. There's no reason to believe it contains a null-terminated string. Therefore, the call to strlen()
could read off the end of the buffer.
In any case, I'm not sure what you expect the loop to do. In the first iteration, i
is 0. If the call to strlen()
does not segfault, then the loop body stores 0 in buf[0]
. Therefore, on the next iteration of the loop, strlen(buf)
will be 0, i
will be 1 (which is not less than 0), so the loop will terminate.
The second print of f1 address: 4196604
is when the parent process continues after the vfork()
-ed subprocess exits. The parent process continues and calls f1()
which prints that.
The numbers that you print are the addresses of f1
and f2
themselves. Why would you expect the address of f1
to be the same as the address of f2
? They are not, so they print different addresses.
On the other hand, the address of f1
is the same in the parent process and the subprocess, since the subprocess shares the parent's address space. So, the same address is printed for f1
both times.
Upvotes: 0