11--fcntl函数(UNIX) | |
| |
网友:cdblsc 发布于: 2007.04.25 14:19 (共有条评论) 查看评论 | 我要评论 | |
fcntl函数可以改变已经打开文件的性质。 #include #include #include int fcntl(int filedes,int cmd,.../* int arg */); 返回:若成功则依赖于cmd(见下),若出错为-1 在本节的各实例中,第三个参数总是一个整数,与上面所示函数原型中的注释部分相对应。但是以后说明记录锁时,第三个参数则是指向一个结构的指针。 fcntl函数有五种功能: 复制一个现存的描述符 (cmd=F_DUPFD)。 获得/设置文件描述符标记 (cmd=F_GETFD或F_SETFD)。 获得/设置文件状态标志 (cmd=F_GETFL或F_SETFL)。 获得/设置异步I/O有权 (cmd=F_GETOWN或F_SETOWN)。 获得/设置记录锁 (cmd=F_GETLK,F_SETLK或F_SETLKW)。 我们先说明这十种命令值中的前七种(说明记录锁时说明后三种,它们都与记录锁有关) 我们将涉及与进程表项中各文件描述符相关联的文件描述符标志,以及每个文件表项中的文件状态标志。 1 F_DUPFD 复制文件描述符filedes,新文件描述符作为函数值返回。它是尚未打开的各描述符中大于或等于第三个参数值(取为整型值)中各值的最小值。新描述符与filedes共享同一文件表项。但是,新描述符有它自己的一套文件描述符标志,其FD_CLOEXEC文件描述符标志则被清除(这表示该描述符在exec时仍保持开放,我们将在以后对此进行讨论。 2 F_GETFD 对应于filedes的文件描述符标志作为函数值返回。当前只定义了一个文件描述符标志FD_CLOEXEC。 3 F_SETFD 对于filedes设置文件描述符标志。新标志值按第三个参数(取为整型值)设置。应当了解很多现存的涉及文件描述符标志的程序并不使用常数FD_CLOEXEC,而是将此 标志设置为0(系统默认,在exec时不关闭)或1(在exec时关闭)。 4 F_GETFL 对应于filedes的文件状态标志作为函数值返回。在说明open函数时,已说明了文件状态标志。如下对于fcntl的文件状态标志: 文件状态标志 说明 O_RDONLY 只读打开 O_WRONLY 只写打开 O_RDWR 读/写打开 O_APPEND 写时都添加至文件尾 O_NONBLOCK 非阻塞方式 O_SYNC 等待写完成 O_ASYNC 异步I/O(仅4.3+BSD) 不幸的是,三个存取方式标志(O_RDONLY,O_WRONLY,以及O_RDWR)并不各占1位。(正如前述,这三种标志的值各是0、1和2,由于历史原因。这三种值互斥—一个文件只能有这三种值之一。)因此首先必须用屏蔽字O_ACCMODE取得存取方式位,然后将结果与这三种值相比较。 5 F_SETFL 将文件状态标志设置为第三个参数的值(取为整型值)。可以更改的几个标志是:O_APPEND,O_NONBLOCK,O_SYNC和O_ASYNC。 6 F_GETOWN 取当前接收SIGIO和SIGURG信号的进程ID或进程组ID。 7 F_SETOWN 设置接收SIGIO和SIGURG信号的进程ID或进程组ID。正的arg指定一个进 程ID,负的arg表示等于arg绝对值的一个进程组ID。 fcntl的返回值与命令有关。如果出错,所有命令都返回-1,如果成功则返回某个其他值。下列三个命令有特定返回值:F_DUPFD,F_GETFD,F_GETFL以及F_GETOWN。第一个返回新 的文件描述符,第二个返回相应标志,最后一个返回一个正的进程ID或负的进程组ID。 下面的程序取指定一个文件描述符的命令行参数,并对于该描述符打印其文件标志说明: #include #include #include "ourhdr.h" int main(int argc,char **argv) { int accmode,val; if(argc != 2 ) err_quit("usage: a.out "; if( (val = fcntl(atoi(argv[1]),F_GETFL,0)) if( val & O_APPEND ) printf(", append"); if( val & O_NONBLOCK ) printf(", nonblocking"); #if!defined(_POSIX_SOURCE) && defined(O_SYNC) if( val & O_SYNC ) printf(", synchronous writes"); #endif putchar('\n'); exit(0); } 在修改文件描述符标志或文件状态标志时必须谨慎,先要取得现在的标志值,然后按照希望修改它,最后设置新标志值。不能只是执行F_SETFD或F_SETFL命令,这样会关闭以前设置的标志位。 下面程序是一个对于一个文件描述符设置一个或多个文件状态标志的函数: 程序: 3-5 #include #include void set_fl(int fd,int flags) { int val; if((val=fcntl(fd,F_GETFL,0)) 如果将中间的一条语句改为: val&=~flags; /*turnflagsoff*/ 就构成了另一个函数,我们称其为clr_fl,并将在后面某个例子中用到它。此语句使当前文件状态标志值val与flags的反码逻辑与运算。 如果在程序的开始处,加上下面一行以调用set_fl,则打开了同步写标志。 set_fl(STDOUT_FILENO,O_SYNC); 这就造成每次write都要等待,直至数据已写到磁盘上再返回。在UNIX中,通常write只是将数据排入队列,而实际的I/O操作则可能在以后的某个时刻进行。数据库系统很可能需要使用O_SYNC,这样一来,在系统崩溃情况下,它从write返回时就知道数据已确实写到了磁盘 上。 程序运行时,设置O_SYNC标志会增加时钟时间。为了测试这一点,运行测试程序,它从磁盘上的一个文件中将1.5M字节复制到另一个文件中。然后,在此程序中设置O_SYNC标志,使其完成上述同样的工作,将两者的结果进行比较,见表3-3。 表3-3 用同步写(O_SYNC)的时间结果 操作 用户CPU(秒) 系统CPU(秒) 时钟时间(秒) 取自表3-1BUFFSIZE=8192的读时间 0.0 0.3 0.3 盘文件的正常write 0.0 1.0 2.3 O_SYNC设置的盘文件write 0.0 1.4 13.4 表3-3中的3行都是在BUFFSIZE为8192的情况下测量得到的。表3-3中的第2行对应于读一个磁盘文? |
fcntl 函数
最新推荐文章于 2024-05-18 00:47:18 发布