基本上,我在为系统编程课做一些功课时想出了一个奇怪的思想实验。我回来的行为有点令人惊讶,我想知道是否有人可以解释发生了什么。
我有这两个源文件:
prog.c中:
#include <fcntl.h>
#include <stdio.h>
int main()
{
printf("%d\n", close(3));
return 0;
}
shell.c:
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
extern char **environ;
int main()
{
char *args[] = {"prog", NULL};
int fd = open("prog", O_RDONLY);
fexecve(fd, args, environ);
printf("-> %d\n", close(fd));
return 0;
}
当我运行shell
时,它打开prog
,它获取文件描述符3.当我运行fexecve
时,它调用prog,关闭FD 3,打印返回值,以及退出。基本上,我正在执行文件which does nothing but close itself!
我发现奇怪的是,当我这样做时,第二个打印语句(shell.c:14
)永远不会到达,因为
control永远不会返回shell程序。 return 0;
中的prog
会终止整个过程。我通过gdb进行了调查:
(gdb) break main
Breakpoint 1 at 0x40065e: file shell.c, line 9.
(gdb) r
Starting program: /home/kebertx/shell
Breakpoint 1, main () at shell.c:9
9 char *args[] = {"prog", NULL};
(gdb) n
10 int fd = open("prog", O_RDONLY);
(gdb)
12 fexecve(fd, args, environ);
(gdb)
process 4256 is executing new program: /home/kebertx/prog
Breakpoint 1, main () at prog.c:6
6 printf("%d\n", close(3));
(gdb)
0
8 return 0;
(gdb)
9 }
(gdb)
0x00007ffff7a58800 in __libc_start_main () from /usr/lib/libc.so.6
(gdb)
Single stepping until exit from function __libc_start_main,
which has no line number information.
[Inferior 1 (process 4256) exited normally]
(gdb) quit
我的直觉让我失望了。 FD 3已成功关闭,但这会导致程序丢失。不应该fexecve
在调用堆栈上吗?为什么要让exec找回原来的路径,为什么需要打开子进程的文件?什么是exec函数正在做什么,以及当我像这样打破它时它们无法做什么?
我不认为这对于实际应用来说应该是我需要知道的东西,但我很好奇。任何解释都将不胜感激!