APUE习题8.7解答
APUE的8.7习题是关于exec的一个问题,书中描述了一句“POSIX.1明确要求再执行exec时关闭打开的目录流”。我们需要自己来验证下这个性质是否在自己的系统上有效,题目给我们提供了思路。
简单的分析下,我们首先需要打开一个目录,这个很简单,使用 opendir() 函数,我们现在获得是 DIR* 的变量,而我们要的是文件描述符fd,所以我们接着调用一个 dirfd() ,将获得目录的文件描述符。有了这些准备工作,我们就可以使用 fcntl() 获得执行时关闭状态(close-on-exec).
接着我们简单的判断一下此时这个状态是否打开的。这一步有利于我们接下来的判断。接着我们将这个fd写入到一个数组里面。用处在下面调用execl时最为参数使用。
我们创建一个进程,在子进程中我们调用execl函数,执行另一个程序,这个程序是利用刚才的描述符,尝试去在调用exec时候打开一个目录,看是否能打开。这就是这个程序的关键。
接着我们来尝试着code。
exercise8-7.c
1
#include<dirent>
/*
opendir()
*/
2
#include<unistd.h>
/*
execl(),fcntl()
*/
3
...
/*
一些必要的头文件
*/
4
5
int
main(
void
)
6
{
7
DIR *
dir;
8
int
val, fd;
9
char
buf[
10
];
/*
for save fd
*/
10
11
dir = opendir(
"
/
"
);
12
fd =
dirfd(dir);
13
14
if
((val = fcntl(fd,F_GETFD,
0
)) <
0
)
15
perror(
"
fcntl
"
);
16
if
(val &
FD_CLOEXEC)
17
printf(
"
close-on-exec is on\n
"
);
18
else
19
printf(
"
clsose-on-exec is off\n
"
);
20
21
sprintf(buf,
"
%d\0
"
,fd);
22
23
if
((pid = fork()) <
0
)
24
perror(
"
fork
"
);
25
else
if
(pid ==
0
)
26
{
27
execl(
"
/home/jesse/test/exercise8.7_child
"
,
"
exercise8.7_child
"
,buf,NULL);
28
exit(
0
);
29
}
30
31
return
0
;
32
}
上面就是我们的一个基本的框架,接着就是再exercise8.7_child.c中实现一个调用,这个就是很简单了。
exercise8.7_child.c
1
#include<fcntl.h>
/*
fcntl()
*/
2
...
/*
一些必要的头文件
*/
3
4
int
main(
int
argc ,
char
*
argv[])
5
{
6
int
fd,val;
7
8
sscanf(argv[
1
],
"
%d
"
, &
fd);
9
if
((val = fcntl(fd,F_GETFD,
0
)) <
0
)
10
perror(
"
fcntl
"
);
11
if
(val &
FD_CLOEXEC)
12
printf(
"
close-on-exec is on\n
"
);
13
else
14
printf(
"
clsose-on-exec is off\n
"
);
15
return
0
;
16
}
我们执行一下
1
jesse@jesse:~/APUE/process$ ./a.
out
2
close-on-exec
is
on
3
jesse@jesse:~/APUE/process$ fcntl: Bad file descriptor
我们会发现,fcntl报错了。说明这个fd不存在,也就是验证了这个确实是在执行exec的时候,将文件描述符关闭了。
我们可以再延伸一些,我们试着将这个标志位关闭,看看结果如何,我们猜想应该是会显示“close-on-exec is off"
我们使用diff,看看哪儿需要更改
jesse@jesse:~/APUE/process$ diff -u exercise8.
7
.c exercise8.7_child.c
--- exercise8.
7
.c
2014
-
04
-
25
10
:
57
:
23.004544016
+
0800
+++ exercise8.7_child.c
2014
-
04
-
25
11
:
11
:
14.064562979
+
0800
@@
-
19
,
8
+
19
,
6
@@
printf(
"
close-on-exec is on\n
"
);
else
printf(
"
close-on-exec is off\n
"
);
- val &= ~
FD_CLOEXEC;
-
fcntl(fd,F_SETFD,val);
sprintf(strfd,
"
%d\0
"
,fd);
if
((pid = fork()) <
0
)
更改的就两行,利用F_SETFD,来实现的。
执行的结果
1
jesse@jesse:~/APUE/process$ ./a.
out
2
close-on-exec
is
on
3
jesse@jesse:~/APUE/process$ close-on-exec
is
off
结果符合猜想。
系统默认的是保持FD_CLOEXEC这个标志打开的,也就是说执行exec的时候是会关闭打开的目录的。

