文件描述符

来源:互联网 发布:厦门软件培训 编辑:程序博客网 时间:2024/06/06 02:09

概要

文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。但是文件描述符这一概念往往只适用于UNIX、Linux这样的操作系统。

优点

文件描述符的优点主要有两个:

  • 基于文件描述符的I/O操作兼容POSIX标准。
  • 在UNIX、Linux的系统调用中,大量的系统调用都是依赖于文件描述符。

例如,下面的代码就示范了如何基于文件描述符来读取当前目录下的一个指定文件,并把文件内容打印至Console中。

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h> int main(void){    int fd;    int numbytes;    char path[] = "file";    char buf[256];     /*     * O_CREAT: 如果文件不存在则创建     * O_RDONLY:以只读模式打开文件     */    fd = open(path, O_CREAT | O_RDONLY, 0644);    if(fd < 0){        perror("open()");        exit(EXIT_FAILURE);    }     memset(buf, 0x00, 256);    while((numbytes = read(fd, buf, 255)) > 0){        printf("%d bytes read: %s", numbytes, buf);        memset(buf, 0x00, 256);    }    close(fd);    exit(EXIT_SUCCESS);}

此外,在Linux系列的操作系统上,由于Linux的设计思想便是把一切设备都视作文件。因此,文件描述符为在该系列平台上进行设备相关的编程实际上提供了一个统一的方法

缺点

文件描述符的概念存在两大缺点:

  • 非UNIX/Linux操作系统上(如Windows NT),无法基于这一概念进行编程。
  • 由于文件描述符在形式上不过是个整数,当代码量增大时,会使编程者难以分清哪些整数意味着数据,那些意味着文件描述符。因此,完成的代码可读性也就会变得很差,这一点一般通过消除魔术数字来解决。

其他

  • 对于ANSI C规范中定义的标准库的文件I/O操作。ANSI C规范给出了一个解决方法,就是使用FILE结构体的指针。事实上,UNIX/Linux平台上的FILE结构体的实现中往往都是封装了文件描述符变量在其中。
  • 在UNIX/Linux平台上,对于控制台(Console)的标准输入,标准输出,标准错误输出也对应了三个文件描述符。它们分别是0,1,2。在实际编程中,如果要操作这三个文件描述符时,建议使用<unistd.h>头文件中定义的三个宏来表示: STDIN_FILENO, STDOUT_FILENO以及STDERR_FILENO。
  • 对于一个进程而言,文件描述符的变化范围为0~OPEN_MAX[1].

与文件描述符相关的操作

文件描述符的生成

  • open(), open64(), creat(), creat64()
  • socket()
  • socketpair()
  • pipe()

与单一文件描述符相关的操作

  • read(), write()
  • recv(), send()
  • recvmsg(), sendmsg()
  • sendfile()
  • lseek(), lseek64()
  • fstat(), fstat64()
  • fchmod()
  • fchown()

与复数文件描述符相关的操作

  • select(), pselect()
  • poll()

与文件描述符表相关的操作

  • close()
  • dup()
  • dup2()
  • fcntl (F_DUPFD)
  • fcntl (F_GETFD and F_SETFD)

改变进程状态的操作

  • fchdir()
  • mmap()

与文件加锁的操作

  • flock()
  • fcntl (F_GETLK, F_SETLK and F_SETLKW)
  • lockf()

与套接字相关的操作

  • connect()
  • bind()
  • listen()
  • accept()
  • getsockname()
  • getpeername()
  • getsockopt(), setsockopt()
  • shutdown()
0 0