您的位置:

Linux文件描述符(fd)的使用方法与注意事项

一、文件描述符概述

文件描述符是Linux系统中对打开文件的引用,每个进程都有自己的文件描述符表。在进程中打开文件时,会返回一个整型的文件描述符,用来标识该文件。文件描述符的值从0开始,每打开一个文件,描述符的值就会递增。在C语言中,文件描述符用int类型来表示。

在Linux中,文件描述符不仅仅可以表示已经打开的普通文件,还可以用于表示管道操作,套接字、目录和设备等。

二、文件描述符的使用方法

1、打开文件

在Linux中,打开文件的函数为open(),示例代码如下:

#include <fcntl.h>
#include <errno.h>

int fd = open("file.txt", O_RDONLY);
if(fd == -1) {
    perror("open file.txt error:");
    exit(EXIT_FAILURE);
}

上述代码中,指定的文件名为file.txt,文件的打开方式为只读模式,函数返回的是文件描述符,如果返回值等于-1,表示打开文件失败。

2、读写文件

在Linux中,读取和写入文件的函数分别为read()和write(),示例代码如下:

读取文件示例:

#include <unistd.h>
#include <errno.h>

char buffer[1024];
int ret;

ret = read(fd, buffer, sizeof(buffer));
if(ret == -1) {
    perror("read error:");
    exit(EXIT_FAILURE);
}

写入文件示例:

#include <unistd.h>
#include <errno.h>

char buffer[1024] = "Hello World!";
int ret;

ret = write(fd, buffer, sizeof(buffer));
if(ret == -1) {
    perror("write error:");
    exit(EXIT_FAILURE);
}

3、关闭文件

在完成对文件的操作后,需要关闭文件,释放资源。关闭文件的函数为close(),示例代码如下:

#include <unistd.h>

close(fd);

三、文件描述符的注意事项

1、资源限制

系统资源有限,每个进程可以打开的文件数是有限制的。默认情况下,每个进程可以打开的文件数为1024个,可以通过ulimit命令查看。

当进程打开的文件数达到系统限制时,会导致无法打开新的文件,可以通过增加系统限制或者调整进程的逻辑来解决。

2、文件描述符的复制

Linux中的文件描述符是引用文件的方式,可以利用dup() or dup2()函数将一个文件描述符复制到另一个文件描述符,以便将一个已经打开的文件描述符传递给一个函数。

例如:

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int fd1 = open("file1.txt", O_RDONLY);
int fd2 = dup(fd1);

上述代码中,fd2是通过将fd1复制而来的文件描述符,它们引用同一个文件。

3、文件描述符的关闭

在使用文件描述符时,要注意及时关闭文件,否则会浪费系统资源,造成不必要的麻烦。当一个进程以当前用户权限打开一个文件后,该文件的所有权就属于了该进程,而不是当前用户。

如果在打开文件后,删除了该文件,但进程还没关闭该文件,则该文件仍然可以继续访问和修改,因为该文件的所有权已经属于了进程,不受文件删除的影响。

4、文件描述符的作用域

文件描述符的作用域默认情况下只在进程内有效,而无法在进程之间进行传递。如果需要在进程之间传递文件描述符,则可以使用Unix域套接字。

例如:

int socketpair(int domain, int type, int protocol, int sv[2]);

/*创建两个进程之间的管道*/
int fd[2];
socketpair(AF_UNIX, SOCK_STREAM, 0, fd);
pid_t pid;
pid = fork();
if (pid < 0) {
    perror("fork error:");
    return -1;
} else if (pid == 0) {
    /* 子进程向父进程发送信息 */
    char *buffer = "Hello World";
    write(fd[1], buffer, strlen(buffer));
    close(fd[1]);
} else {
    /* 父进程接收子进程发送的信息 */
    char buffer[1024];
    memset(buffer, 0, 1024);
    read(fd[0], buffer, 1024);
    printf("Message from child process: %s\n", buffer);
    close(fd[0]);
}

总结

文件描述符是Linux系统中对打开文件的引用,每个进程都有自己的文件描述符表。在使用文件描述符时,要注意及时关闭文件,否则会浪费系统资源。

文件描述符的作用域默认情况下只在进程内有效,如果需要在进程之间传递文件描述符,则可以使用Unix域套接字。