我的UNIX编程学习笔记——文件描述符与open函数

时间:2020-12-04 19:25:35

文件描述符与open函数

一、文件描述符

         对于文件描述符我们可以这样理解,文件描述符是作为打开文件的一个标记,且每个文件描述符对应一个唯一的打开文件。通常可以期望文件描述符0、1、2分别对应的是标准输入(STDIN_FILENO)、标准输出(STDOUT_FILENO)和标准错误输出(STDERR_FILENO)。

         文件描述符会是一个非负数,其变化范围一般是0~OPEN_MAX。现在的UNIX系统中允许一个进程打开的文件相对已经不少了,但是这并不是无限制的,文件描述符是会有一个上限的。而且进程究竟能打开多少文件还会受到来自系统管理员的限制,因为打开过的的文件会占用系统资源,所以一般来说管理员会给予一定的限制。

二、open函数

open函数说明

         open函数通常用于打开或者创建一个文件,其函数原型为:

         int open(const char *pathname, int oflag, …)

         函数执行成功则返回一个可用的最小文件描述符,出错则返回-1并设置errno。

         open函数的第一个参数表示要打开文件的名字,第二个参数为打开文件的方式,函数的第三个参数只有在创建一个文件时才有效,这个参数指定了创建文件的权限。

         我们需要指定一种打开文件的方式,而且必须在读模式打开(O_RDONLY)、写模式(O_WRONLY)打开和读写模式(O_RDWR)打开之中指定一种模式。另外还可以额外指定下面的几种模式,这些可以与上面指定的打开方式进行与运算。

1、  O_APPEND 指定这该模式后,每次写入都会将内容写到文件的结尾处,写入的时候将无视lseek函数之前设置的文件偏量。

2、  O_CREAT 指定此参数的时候将创建一个文件,如果指定的文件已经存在,那么会删除这个文件并创建一个新的文件。

3、  O_EXCL   可以与O_CREAT参数同时指定,此时open函数会创建指定文件,若指定文件存在open函数将返回出错。注意此时检查和创建文件成为一个原子操作。

4、  O_TRUNC 若指定了这个参数,当文件存在且以只写或读写的模式打开时将文件的长度截短为0。

5、  O_NOCTTY 此时如果pathname是一个终端设备,那么不将该设备分配为打开该设备进程的控制终端。

6、  O_NONBLOCK 如果pathname为管道、块特殊文件或者字符特殊文件,那么本次打开以及后续的I/O操作为非阻塞。

         下面的三个模式也是可以选择的而且只能同时指定其中的一种,这些模式与UNIX中同步输入和输出有关。但是要注意,指定下面这几种模式时的具体行为可能与系统实现有关。

1、  O_DSYNC 每次写入都需要等待实际I/O操作的完成,但是如果写操作不影响读取刚刚写入的内容,则不等待文件属性的更新。

2、  O_RSYNC 指定该模式时,以这个open函数打开文件描述符为参数的读操作阻塞,直到对文件相同部分写操作完成(若此时读与写的内容都是文件的同一部分)。

3、  O_SYNC  等待所有I/O操作完成,包括对文件属性的更新。

可能导致open函数出错的原因

         多数情况下open函数出错往往是因为权限问题或者是来自管理员的限制,例如当前用户打开了足够多的文件以至于达到允许打开文件的上限,那么显然open函数会返回-1并设置相应的errno。还有如果以读的方式打开一个文件,但是当前用户(一般用户)对文件没有读的权限,那么就会因为文件权限问题导致函数返回错误。当试图使用open函数创建一个文件但是没有写相关目录的权限的时候同样会发生错误。

         总之,在使用open函数的时候要注意打开文件可能存在的权限问题。文件权限决定了我们可以对这个文件做怎样的一个操作,尤其是要考虑调用程序的用户很可能不会是超级用户,因此往往会受到各种权限的限制。除此之外还要注意,如果参数pathname指向的字符串过长的话也同样会出现问题。对于一个好的实现,在这种情况下可能会返回一个错误。

文件名与路径名截短问题

         文件名与路径名截短问题是一个比较有趣的问题,一个UNIX系统中当然不会允许路径名或者某个文件名过长的。对于过长的文件名或者路径名一些系统会将其进行截短,而另一些系统在这个时候会直接返回一个错误并将errno的值设置为ENAMETOOLONG。从某种意义上来看第二种处理的方式显然是要更好一些的,因为在采用第一种处理方式处理过长文件或路径名的系统中有事很难判断出究竟是否发生过截短,如果这个文件名正好达到了允许最大长度,这样会带来很多的问题。

         在早期的系统中这个问题表现的比较明显,这些系统中允许的最长文件名或路径名相对较短,因此比较容易出现这类问题。现在比较流行的UNIX(UNIX Like)系统中,一般允许的最长的文件名和路径名都比较长,多数情况下不需要特意的去考虑这个问题。毕竟正常情况下不会有人去特意的去制造很长的一个路径或者是过长的文件名,这样会给管理造成不必要的麻烦。但是我们不能排除会发生这种情况的可能性,故对文件名和路径名的截短问题我们仍然需要有一定的了解。