exec在执行前会关闭所有打开的目录流(DIR)
-
检查文件描述符状态标志,
-
dirfd(DIR *)
得到目录的文件描述符 -
重要的
fcntl()
函数,得到文件描述符状态 -
忽略了
exec
族函数的第一个参数的作用导致调用exec
一直成功exec
的第一个参数一般是可执行文件的文件名,The first argument, by convention, should point to the filename associated with the file being executed.
-
一定要注意如果使用标准IO,就要想到缓冲的方式,不然会以为是逻辑的错误
-
// 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);
}
// 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
的代码
#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);
}
- 用非缓冲看
fork
的子进程执行情况