dup和dup2函数:
int dup(int fd) ;
int dup2(int fd, int fd2) ;
dup和dup2都可以用来复制一个现有的文件描述符,返回的新的文件描述符与fd共享一个文件表项。
两者不同之处是,dup2可以用参数fd2指定新的描述符。若fd2已经打开,则先将其关闭。若fd等于fd2,则不关闭它。
fcntl函数的功能之一就是复制一个现有的描述符。
而调用
dup2(fd, fd2) ;
等效于
close(fd2);
fcntl(fd, F_DUPFD, fd2);
现要求不使用fcntl来实现dup2的功能。
用dup函数来实现。因为dup返回的文件描述符一定是当前可用文件描述符中的最小数值,可利用这一性质,从0至fd2均复制fd,当复制出错或返回值等于fd2时结束循环,在这一过程中标记复制成功且返回的文件描述符不等于fd2的下标,最后关闭所有标记的文件描述符。
代码如下:
#include <stdio.h>
#include <apue.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
int mydup2(int fd, int fd2);
int main(int argc, char **argv)
{
int fd = open("test", O_RDWR | O_CREAT);
int fd2 = 6;
if((fd2 = mydup2(fd, fd2)) == -1)
{
err_quit("mydup2 error");
}
char *s = "this is a test of dup and dup2\n";
if(write(fd2, s, strlen(s)) == -1)
{
err_sys("write error");
}
exit(0);
}
int mydup2(int fd, int fd2)
{
printf("%d \t %d\n", fd, fd2);
int temp;
if((temp = dup(fd)) == -1)
{
err_sys("the parameter fd is invalid");
return -1;
}
else
{
close(temp);
}
if(fd == fd2)
{
return fd;
}
close(fd2);
int *field = (int*)malloc(fd2*sizeof(int));
int i, tempfd;
for(i = 0; i <= fd2; ++i)
{
field[i] = 0;
if((tempfd = dup(fd)) == -1)
{
err_sys("dup error");
free(field);
return -1;
}
else
{
if(tempfd == fd2)
{
break;
}
else
{
field[i] = 1;
}
}
}
for(i = 0; i < fd2; ++i)
{
if(field[i])
close(i);
}
free(field);
return tempfd;
}