说明:只供学习交流,转载请注明出处
Linux程序开发中,常遇到需要将某个文件描述符赋值给其他变量的情况。例如,将文件复制到标准输入输出中,这时就要使用dup或dup2函数。dup与dup2函数常用于实现输入、输出的重定向。这两个函数的具体信息如表所示:
dup,dup2函数
头文件 | <unistd.h> | ||
函数形式 | int dup(int oldfd); int dup2(int oldfd, int newfd); | ||
返回值 | 成功 | 失败 | 是否设置errno |
返回新的描述符 | -1 | 是 |
说明:dup函数用于复制指定的文件描述符。函数返回新的描述符是当前进程最小的未使用的描述符。
dup2函数同样用于复制指定的文件描述符,只是参数与dup函数存在不同。如果新的文件描述符已经打开(在函数参数中即为newfd),则会先关闭新的文件描述符。
在Linux系统中还定义了如下的宏,方便程序员对标准输入、输出和错误输出进行控制。
STDIN_FILENO:标准输入,其值为0。
STDOUT_FILENO:标准输出,其值为1。
STDERR_FILENO:标准错误输出,其值为2。
错误信息:
EBADF:oldfd不是打开的文件描述符,或newfd超出了文件描述符充许的范围。
EBUSY:在使用open函数和dup函数时发生了冲突,dup2函数返回该错误。
EMFILE:进程打开文件达到上限。
EINTR:dup2函数调用被信号中断。
实例:
程序通过调用dup函数实现了对标准输出的控制。程序首先关闭了标准输出文件描述符,然后调用dup函数,将打开的文件描述符重定向到标准输出上(因为dup函数返回的新的描述符是当前进程最小的、未使用的描述符,而现在标准输出关闭后,其就是最小并未使用的描述符)。接着,使用printf语句来验证结果,按预计该条输出应该输入到打开的文件中。具体代码如下:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int fd1;
if ( argc != 2 )
{
printf("Usage: %s filename\n");
return (1);
}
if ((fd1=open(argv[1], O_CREAT | O_RDWR, 0777))==-1)
{
perror("Cannot create the file");
return (1);
}
close(STDOUT_FILENO);
if (dup(fd1) == -1)
{
perror("Cannot reserved the std out fd");
return (1);
}
printf("Write the file\n");
close(fd1);
return (0);
}
运行结果为:
[root@localhost test]# ls
1 2.cpp dup hello.c lseek open read test test.dat write.c
1.c dest dup.c hello.txt lseek.c open.c read.c test.c write
[root@localhost test]# ./dup happy
[root@localhost test]# more happy
Write the file
[root@localhost test]#
也可以使用dup2函数来实现相同的功能。dup2函数在重定向时,如果newfd是打开的话,会首先关闭newfd。因此
close(STDOUT_FILENO);
if (dup(fd1) == -1)
{
perror("Cannot reserved the std out fd");
return (1);
}
需要修改成:
if (dup2(fd1, STDOUT_FILENO) == -1)
{
perror(“Cannot reserved the std out fd”);
return (1);
}