APUE學習手札 編寫一個與3.12節中dup2功能相同的函數,要求不呼叫fcntl函數,並且要有正確的出錯處理

2020-10-01 08:00:02

3.2 編寫一個與3.12節中dup2功能相同的函數,要求不呼叫fcntl函數,並且要有正確的出錯處理。

思路,不斷執行dup函數,直到返回與newfd相同的檔案描述符,所有都執行結束之後關閉之前dup返回的檔案描述符

不要忘記特判newfd和fd相同的情況,直接返回。記住dup2還多了一歩先關閉newfd的步驟

#include "apue.h"
#define BUFFSIZE 16
int main()
{
	char buffer[BUFFSIZE];
	int fdin,fdout,n;
	fdin=my_dup(STDIN_FILENO,3);
	fdout=my_dup(STDOUT_FILENO,4);
	if(fdin==-1||fdout==-1)
	{
		err_sys("my_dup error!");
		return -1;
	}
	else
	{
		printf("STDIN fd : %d\n", fdin);
		printf("STDOUT fd : %d\n", fdout);
		while((n=read(fdin,buffer,BUFFSIZE))>0)
		{
			if(write(fdout,buffer,n)!=n)
			{
				err_sys("write error!\n");
			}
		}
		if(n < 0)printf("read error");
	}
	return 0;
}
int my_dup(int fd,int newfd)
{

	if(fd==newfd)return fd;
	if(fd<0||fd>FOPEN_MAX)
    {
        printf("fd is wrong.\n");
        return -1;
    }
    if(newfd <0||newfd>FOPEN_MAX)
    {
        printf("newfd is wrong.\n");
        return -1;
    }
	close(newfd);
	int fileindex[newfd+1];
	int index=0;
	while((fileindex[index++]=dup(fd))!=newfd)
	{
		printf("result after dup(fd):%d\n",fileindex[index-1]);
		if(fileindex[index-1]==-1)
		{
			err_sys("my_dup error!");
			return -1;
		}
	}
	int i=0;
	for(;i<index-1;i++)
	{
		close(fileindex[i]);
	}
	return fileindex[index-1];
	
}

執行結果:

在伺服器上編寫3.2.c的原始碼,編譯,執行後如下圖:

0mPMqS.png

編譯生成了一個3.2的執行檔案,上述程式碼的功能是複製了STDIN_FILENO和STDOUT_FILENO這兩個檔案描述符,分別返回4和5

編譯生成了一個3.2的執行檔案,上述程式碼的功能是複製了STDIN_FILENO和STDOUT_FILENO這兩個檔案描述符,分別返回4和5

再通過讀寫驗證my_dup是否呼叫成功,出錯處理也在程式中有體現。