文件描述符复制和重定向
主要介绍另几个可以用来分配文件描述符的函数
1. dup
dup
函数是一个用于复制文件描述符的系统调用,它创建一个新的文件描述符,该描述符与原始描述符指向相同的文件、管道或套接字。dup
函数的原型如下:
#include <unistd.h>
int dup(int oldfd);
oldfd
是要复制的文件描述符。
dup
返回的新文件描述符是系统中当前可用的最小文件描述符。如果复制成功,它与 oldfd
指向相同的文件表项。这意味着,对于新的文件描述符和原始文件描述符,共享相同的文件偏移量、文件状态标志和文件打开/关闭状态。
以下是一个简单的示例,演示如何使用 dup
函数:
///
// Created by kk on 2024/1/4.
//
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main(){
int fd1, fd2;
char buffer[20];
// 打开一个文件
fd1 = open("example.txt", O_RDONLY);
if (fd1 == -1) {
perror("open");
exit(EXIT_FAILURE);
}
// 使用 dup 复制文件描述符
fd2 = dup(fd1);
if (fd2 == -1) {
perror("dup");
close(fd1);
exit(EXIT_FAILURE);
}
// 读取并打印文件内容
read(fd1, buffer, sizeof(buffer));
printf("Read from fd1: %s", buffer);
close(fd1);
// 使用新的文件描述符继续读取文件内容
read(fd2, buffer, sizeof(buffer));
printf("Read from fd2: %s", buffer);
// 关闭文件描述符
close(fd2);
return 0;
}
在上述示例中,dup
函数被用于复制文件描述符 fd1
,生成了一个新的文件描述符 fd2
,然后可以通过这两个文件描述符来独立地对同一文件进行操作。需要注意,关闭其中一个文件描述符并不会影响另一个描述符。
在这里插入图片描述
2. dup2
dup2
函数是用于复制文件描述符的系统调用,与 dup
函数类似,但 dup2
允许将新的文件描述符指定为参数,从而更加灵活。dup2
的原型如下:
#include <unistd.h>
int dup2(int oldfd, int newfd);
oldfd
是要复制的文件描述符。newfd
是希望新的文件描述符具有的数值。
返回值
dup2
函数的作用是将 oldfd
复制到 newfd
,如果 newfd
已经打开,它会先关闭 newfd
。如果 oldfd
等于 newfd
,则 dup2
不做任何操作,直接返回 newfd
。
以下是一个简单的示例,演示如何使用 dup2
函数:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main() {
int fd1, fd2;
char buffer[20];
// 打开一个文件
fd1 = open("example.txt", O_RDONLY);
if (fd1 == -1) {
perror("open");
exit(EXIT_FAILURE);
}
// 使用 dup2 复制文件描述符到指定的文件描述符值(e.g., 100)
fd2 = dup2(fd1, 100);
if (fd2 == -1) {
perror("dup2");
close(fd1);
exit(EXIT_FAILURE);
}
printf("fd2 = %d\n", fd2);
// 读取并打印文件内容,使用新的文件描述符
read(fd2, buffer, sizeof(buffer));
printf("Read from fd2 (newfd=100): %s\n", buffer);
// 关闭文件描述符
close(fd1);
close(fd2);
return 0;
}
在上述示例中,dup2
函数被用于将文件描述符 fd1
复制到新的文件描述符 100
,然后通过新的文件描述符 100
对文件进行读取操作。需要注意的是,dup2
在执行时会先关闭目标文件描述符 newfd
,因此在实际应用中,应确保 newfd
不是一个已经被打开的文件描述符,或者需要在使用前关闭。
3. fcntl
fcntl
(file control)是一个用于对文件描述符进行各种控制操作的系统调用。它提供了一系列功能,包括文件状态标志的设置和获取、文件锁定、以及对文件描述符的其他控制操作。fcntl
函数的原型如下:
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */);
fd
是目标文件描述符。cmd
是控制命令,它指定对文件描述符fd
的操作。arg
是一个可选的参数,根据cmd
的不同而有所变化。
以下是一些常用的 fcntl
控制命令:
返回值:函数调用失败返回 -1,调用成功,返回正确的值:
- 参数 cmd = F_DUPFD:返回新的被分配的文件描述符
- 参数 cmd = F_GETFL:返回文件的flag属性信息
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
int fd = open("example.txt", O_RDWR);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
// 获取当前文件状态标志
int flags = fcntl(fd, F_GETFL);
if (flags == -1) {
perror("fcntl F_GETFL");
close(fd);
exit(EXIT_FAILURE);
}
// 设置新的文件状态标志
flags |= O_APPEND; // 添加 O_APPEND 标志
if (fcntl(fd, F_SETFL, flags) == -1) {
perror("fcntl F_SETFL");
close(fd);
exit(EXIT_FAILURE);
}
// 在文件末尾追加数据
write(fd, "Appended text.\n", 15);
close(fd);
return 0;
}
追加数据后: