一、文件描述符概述
文件描述符是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域套接字。