UNIX環境高度プログラミング学習ノート(四)fcntl関数を呼び出さずdup 2の機能を実現


dupとdup 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; }