九、dup(duplicate)和dup2函數
目錄:
- 九、dup(duplicate)和dup2函數
-
-
-
- 一、重定向
- 二、dup()函數原型
-
- int dup(int oldfd);
-
-
- 三、dup2()函數原型
-
- int dup2(int oldfd, int newfd);
-
-
- 四、fcntl()函數實作dup()和dup2()
-
- int new_fd = fcntl(int old_fd, int cmd, int fd_no);
-
一、重定向
現假設有一打開的檔案,該檔案描述符為
old_fd
;
現建立另一個新的檔案描述符
new_fd
,該檔案描述符不指向任何檔案,現使
new_fd
重定向于
old_fd
,則檔案描述符
new_fd
就會指向
old_fd
所描述的檔案,這就是重定向;
最終,相當于
new_fd
和
old_fd
指向同一檔案(最初
old_fd
所指向的檔案),如圖所示:
當然,即使
new_fd
已指向某一檔案,也可以用于重定向
二、dup()函數原型
包含頭檔案:
int dup(int oldfd);
建立一個新的檔案描述符,将新的檔案描述符定向到所描述的檔案,新的檔案描述符序号将是編号最低的未使用的檔案描述符
oldfd
已有的檔案描述符,即重定向目标檔案的檔案描述符,可以是
int oldfd
、
STDIN_FILENO
、
STDOUT_FILENO
STDERR_FILENO
成功時傳回一個新的檔案描述符,失敗傳回 -1,errno,新的檔案描述符序号将是編号最低的未使用的檔案描述符
傳回值
例如:使用重定向的檔案描述符向檔案寫入内容
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
int old_fd = open(argv[1], O_RDWR | O_APPEND);
if(fd == -1)
{
perror("open error");
exit(1);
}
int new_fd = dup(old_fd);
if(new_fd == -1)
{
perror("dup error");
exit(1);
}
printf("new_fd = %d\n", new_fd);
int ret = write(new_fd, "Hello World!\n", 13);
if(ret == -1)
{
perror("write error");
exit(1);
}
return 0;
}
打開檔案後,
old_fd
值為 3,則
new_fd
将是編号最低的未使用的檔案描述符,即
new_fd
值為 4
三、dup2()函數原型
包含頭檔案:
int dup2(int oldfd, int newfd);
将檔案描述符重定向到
newfd
所描述的檔案
oldfd
已有的檔案描述符,即重定向目标檔案的檔案描述符,可以是
int oldfd
、
STDIN_FILENO
、
STDOUT_FILENO
STDERR_FILENO
重定向的檔案描述符
int newfd
失敗時傳回 -1、errno
傳回值
與
dup()
不同的是,
dup()
所建立的新的檔案描述符的編号将是編号最低的未使用的檔案描述符,而
dup2()
則可以由使用者指定 newfd,如圖所示:
相當于:
例如:使用
dup2()
把本來要列印到螢幕上的内容輸出到指定檔案,需要用到标準輸出檔案的宏
STDOUT_FILENO
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
int fd = open(argv[1], O_RDWR | O_APPEND);
if(fd == -1)
{
perror("open error");
exit(1);
}
// 将标準輸出檔案的檔案描述符重定向于 fd 所描述的檔案
int ret = dup2(fd, STDOUT_FILENO);
if(ret == -1)
{
perror("dup2 error");
exit(1);
}
// 向螢幕輸出内容
printf("Hello World!\n");
return 0;
}
原理圖:
四、fcntl()函數實作dup()和dup2()
int new_fd = fcntl(int old_fd, int cmd, int fd_no);
使用函數實作
fcntl()
和
dup()
的功能
dup2()
已存在的檔案描述符
int old_fd
該參數應選擇
int cmd
F_DUPFD
指定
int fd_no
的檔案描述符;若檔案描述符被占用,則
new_fd
的編号将設為 >=
new_fd
的未使用的檔案描述符;若檔案描述符未被使用,則
int fd_no
的編号将設為
new_fd
所指定的編号
fd_no
成功時傳回
傳回值
的檔案描述符,失敗時傳回 -1、errno
new_fd
例如:檢驗
fcntl()
的dup功能
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
int old_fd = open(argv[1], O_RDWR);
if(old_fd == -1)
{
perror("open error");
exit(1);
}
// 檔案描述符0被占用,new_fd1 将被指定為編号最低的未使用的檔案描述符,即 4
int new_fd1 = fcntl(new_fd1, F_DUPFD, 0);
if(new_fd1 == -1)
{
perror("fcntl error");
exit(1);
}
printf("new_fd1 = %d\n", new_fd1);
// 檔案描述符10未被使用,new_fd2 将被指定為 10
int new_fd2 = fcntl(new_fd2, F_DUPFD, 10);
if(new_fd2 == -1)
{
perror("fcntl error");
exit(1);
}
printf("new_fd2 = %d\n", new_fd2);
return 0;
}