UNIX環境高度プログラミング学習ノート(四)fcntl関数を呼び出さずdup 2の機能を実現
4584 ワード
dupとdup 2関数:
dupおよびdup 2は、既存のファイル記述子をコピーし、返される新しいファイル記述子をfdと共有するために使用することができる.両者の違いは、dup 2がパラメータfd 2で新しい記述子を指定できることである.fd 2が既に開いている場合は、先に閉じます.fdがfd 2に等しい場合は、閉じません.fcntl関数の機能の1つは、既存の記述子をコピーすることです.
呼び出し
に等しい
fcntlを用いずにdup 2の機能を実現することが要求される.
dup関数で実現します.dupが返すファイル記述子は、現在使用可能なファイル記述子の最小値であるに違いないため、この性質を利用して、0からfd 2までfdをコピーし、コピーエラーまたは戻り値がfd 2に等しい場合にループを終了し、この過程でタグコピーが成功し、返されたファイル記述子がfd 2の下に等しくなく、最後にすべてのタグのファイル記述子を閉じることができる.
コードは次のとおりです.
int dup(int fd) ;
int dup2(int fd, int fd2) ;
dupおよびdup 2は、既存のファイル記述子をコピーし、返される新しいファイル記述子をfdと共有するために使用することができる.両者の違いは、dup 2がパラメータfd 2で新しい記述子を指定できることである.fd 2が既に開いている場合は、先に閉じます.fdがfd 2に等しい場合は、閉じません.fcntl関数の機能の1つは、既存の記述子をコピーすることです.
呼び出し
dup2(fd, fd2) ;
に等しい
close(fd2);
fcntl(fd, F_DUPFD, fd2);
fcntlを用いずにdup 2の機能を実現することが要求される.
dup関数で実現します.dupが返すファイル記述子は、現在使用可能なファイル記述子の最小値であるに違いないため、この性質を利用して、0からfd 2までfdをコピーし、コピーエラーまたは戻り値がfd 2に等しい場合にループを終了し、この過程でタグコピーが成功し、返されたファイル記述子がfd 2の下に等しくなく、最後にすべてのタグのファイル記述子を閉じることができる.
コードは次のとおりです.
#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
";
if(write(fd2, s, strlen(s)) == -1)
{
err_sys("write error");
}
exit(0);
}
int mydup2(int fd, int fd2)
{
printf("%d \t %d
", 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;
}