APUE习题8.7

exec在执行前会关闭所有打开的目录流(DIR)

  • 检查文件描述符状态标志,

    1. dirfd(DIR *)得到目录的文件描述符

    2. 重要的fcntl()函数,得到文件描述符状态

    3. 忽略了exec族函数的第一个参数的作用导致调用exec一直成功

      exec的第一个参数一般是可执行文件的文件名,

      The first argument, by convention, should point to the filename associated with the file being executed.

    4. 一定要注意如果使用标准IO,就要想到缓冲的方式,不然会以为是逻辑的错误

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// a.c
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h>
#include <dirent.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include "apue.h"

int testDir() {
DIR *dirp;

if ((dirp = opendir("/home/luchao/Documents/Apue/8")) == NULL)
err_sys("opendir error");
int fd = dirfd(dirp);
int status;
if ((status = fcntl(fd,F_GETFD)) == -1)
err_sys("fcntl error");
// 子进程执行exec时关闭所有打开的文件描述符,
if (status & FD_CLOEXEC)
printf("close-on-exec on");
else
printf("close-on-exec close");

// 关闭 close on exec 标志,也就是在调用exec时,不关闭所有的文件描述符
// status &= (~FD_CLOEXEC);
// if ((status = fcntl(fd,F_SETFD,status)) < 0)
// err_sys("fcntl2 error");

return fd;
}

int testFile() {
int fd;
if ((fd = open("/home/luchao/Documents/Apue/8/1.in",O_RDWR)) == -1)
err_sys("open error");
int status;
if ((status = fcntl(fd,F_GETFD,0)) == -1)
err_sys("fcntl error");
if (status & FD_CLOEXEC)
printf("close on exec on");
else
printf("close on exec close");

return fd;
}

int main(int argc,char *argv[]) {
// int fd = testDir();
int fd = testFile();
// setbuf(stdout,NULL);
pid_t pid;
char buf[10];
sprintf(buf,"%d",fd);

if ((pid = fork()) < 0)
err_sys("fork error");
else if (pid == 0) {
char *path = "/home/luchao/Documents/Apue/8/b";
if (execl(path,"b",buf,(char *)0) < 0)
err_sys("execl error");
}

if (waitpid(pid,NULL,0) == -1)
err_sys("error waitpid");
exit(0);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// b.c
#include "apue.h"
#include <fcntl.h>
#include <stdio.h>

int main(int argc,char *argv[]) {
int status,fd;
for (int i=0; i<argc; ++i)
printf("argv[%d] = %s ",i,argv[i]);

if (argv[1] != NULL)
sscanf(argv[1],"%d",&fd);
else
fd = -1;
if ((status = fcntl(fd,F_GETFD,0)) < 0)
err_sys("fcntl error");
if (status & FD_CLOEXEC)
printf("close on exec on");
else
printf("close on exec close");
exit(0);
}
  • 测试可以看出目录流的文件描述符设置了close-on-exec位,而普通文件描述符没有设置

一段理解fork的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <sys/types.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>

int main(int argc,char *argv[]) {
int fd;
if ((fd = open("/home/luchao/Documents/Apue/8/1.in",O_RDWR|O_CREAT,0644)) == -1)
exit(1);
// 调整i< 验证
for (int i=0; i<4; ++i) {
fork();
// 用非缓冲Io看看结果
write(fd,"x",1);
}
exit(0);
}
  1. 用非缓冲看fork的子进程执行情况

fork的进程


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!