文件描述符的复制:
dup和dup2是两个非常有用的系统调用,都是用来复制一个文件的描述符,使新的文件描述符也标识旧的文件描述符所标识的文件。
>> int dup(int oldfd);
>> int dup2(int oldfd,int newfd);
dup和dup2经常用来重定向进程的stdin,stdout和strerr。如:ls > log.txt 将ls的输出信息重定向到log.txt
1、dup函数
#include
int dup(int oldfd);
功能:复制oldfd文件描述符,并分配一个新的文件描述符,新的文件描述符是调用进程文件描述符表中最小可用的文件描述符。
参数:要复制的文件描述符oldfd。
返回值:成功返回新的文件描述符,失败返回-1;错误代码存于errno中。
#include
#include
#include
#include
#include
#include
int main(int argc,char *argv[])
{
int fd,fd1;
fd = open("test.txt",O_CREAT|O_WRONLY,0666);//S_IRWXU
if(fd < 0)
{
perror("open:");
_exit(-1);
}
close(1);
fd1 = dup(fd);
printf("fd1 = %d\n",fd1);
return 0;
}
运行结果如下:
2、dup2:dup的升级版本
#include
int dup2(int oldfd, int newfd);
功能:复制一份打开的文件描述符oldfd,并分配新的文件描述符newfd,newfd也标识oldfd所标识的文件。
注意:newfd是小于文件描述符最大允许值的非负整数(<=1023,总共1024个文件描述符),如果newfd是一个已经打开的文件描述符,则首先关闭该文件,然后再复制。
参数:要复制的文件描述符oldfd,分配新的文件描述符newfd。
返回值:成功返回newfd;失败返回-1,错误代码存于errno中。
#include
#include
#include
#include
#include
#include
int main(int argc,char *argv[])
{
int fd,fd1;
fd = open("test.txt",O_CREAT|O_WRONLY,0666);
if(fd < 0)
{
perror("open:");
_exit(-1);
}
fd1 = dup2(fd,1);//让1也代表fd所代表的文件
printf("fd1 = %d\n",fd1);
return 0;
}
执行结果如下:
3、复制文件描述符后新旧文件描述符的特点
使用dup或dup2复制文件描述符后,新文件描述符和旧文件描述符指向(标识/代表)同一个文件,共享文件的锁定、读写位置和各项权限(只读/只写)。(属性)
当关闭新的文件描述符时,通过旧文件描述符仍可操作文件。
当关闭旧的文件描述符时,通过新的文件描述符仍可操作文件。
4、exec前后文件描述符的特点(进程没有变,即exec之后还能不能用exec前的那张文件描述符的表)
close_on_exec标志决定了文件描述符在执行exec后文件描述符是否可用。
文件描述符的close_on_exec标志默认是关闭的,即文件描述符在执行exec后文件描述符是可用的。
若没有设置close_on_exec标志位,进程中打开的文件描述符,及其相关的设置在exec后不变,可供新启动的程序使用。
设置close_on_exec标志位的方法:
int flags;
flags = fcntl(fd,F_GETFD); //获得标志
flags |= FD_CLOEXEC; //打开标志位
flags &= ~FD_CLOEXEC; //关闭标志位
fcntl(fd,F_SETFD,flags); //设置标志
#include
#include
#include
#include
#include
#include
int main(int argc,char *argv[])
{
int fd_pipe[2];
pid_t pid;
if(pipe(fd_pipe)<0){
perror("pipe");
}
pid = fork();
if(pid < 0){
perror("fork");
_exit(-1);
}
else if(pid == 0){
dup2(fd_pipe[1],1);
execlp("expr","expr","6","+","8",NULL);
}
else{
wait(NULL);
char value[20] = "\0";
read(fd_pipe[0],value,sizeof(value));
printf("value = %s\n",value);
}
return 0;
}
编译执行后结果如下: