自行实现dup2的功能。函数原型:int mydup2(int fd, int fd2),思路如下:
1.fd2小于0,直接返回错误;
2.如果fd是有效的文件描述符且等于fd2,直接返回fd2;
3.如果fd2已经打开,关闭fd2;
4.分配一个长度为fd2值的fdset数组,不断调用dup,直到返回的文件描述符的值和fd2相等;
5.清理资源,返回fd2。
实现的函数代码如下:
#include<stdio.h>
#include<errno.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<string.h>
int mydup2(int fd, int fd2) {
if (fd2 < 0) {
printf("fd2 can not under zero!\n");
return -1;
}
int tempfd = dup(fd);//判断fd是否是打开的文件描述符
if (tempfd == -1) {
printf("dup(fd) %d, error : %s\n", __LINE__, strerror(errno));
return -1;
}
if (fd == fd2) {//fd是已经有效文件描述符,如果和fd2相同,直接返回
return fd2;
}
tempfd = dup(fd2);
if (tempfd == -1) { //fd2可能是沒有打開,也可能是其他原因(man dup查看)
//ignore
} else { //关闭fd2
close(fd2);
close(tempfd);
}
int *fdset = malloc(fd2 * sizeof(int));
int i = 0;
int success = 0;
for (i = 0; i < fd2; i++) {//一般描述符不要写太大,这里不做优化。
if (success == 0) {//如果还没打开到fd2
tempfd = dup(fd);
} else {//如果fd2已经打开了
fdset[i] = 0;
continue;
}
if (tempfd == -1) {
printf("dup(fd) %d, error : %s\n", __LINE__, strerror(errno));
free(fdset);
return -1;
} else if (tempfd == fd2) {
success = 1;
} else {
fdset[i] = tempfd;
}
}
for (i = 0; i < fd2; i++) {
if (fdset[i] != 0) {
close(fdset[i]);
}
}
if (success == 0) {
free(fdset);
printf("my_dup2, %d] error : %s\n", __LINE__, strerror(errno));
return -1;
}
free(fdset);
return fd2;
}
测试代码如下,如果mydup2能成功运行,那么必定会产生文件mydup2file.txt:
int main(int argc, char **argv) {
if (argc != 2) {
printf("usege: ./mydup2 <newfd>\n");
exit(1);
}
umask(0);
int j = 0;
int fd = 0;
for (;j<10;j++) {
fd = open("/home/lhm/桌面/mydup2file.txt", O_CREAT|O_RDWR, S_IRWXU|S_IRWXG);
}
int fd2 = atoi(argv[1]);
if (mydup2(fd, fd2) == -1 ) {
printf("mydup2, %d] error : %s\n", __LINE__, strerror(errno));
exit(1);
}
char *sucMsg = "hello, mydup2 fun success!";
if (write(fd2, sucMsg, 26) != 26) {
printf("error, 一次性無法全部寫入內容!(爲了儘量簡化,不會處理這個問題)\n");
}
close(fd);
close(fd2);
printf("執行成功!\n");
exit(0);
}