Chinaunix首页 | 论坛 | 博客
  • 博客访问: 968966
  • 博文数量: 200
  • 博客积分: 5011
  • 博客等级: 大校
  • 技术积分: 2479
  • 用 户 组: 普通用户
  • 注册时间: 2008-06-27 15:07
文章分类

全部博文(200)

文章存档

2009年(12)

2008年(190)

我的朋友

分类:

2008-10-29 16:07:01

3.9 i/o efficiency

在重复的读取文件中的数据的时候,每次读取的数据量大小如果接近磁盘的block_size的话,效率是比较高的。

3.13 sync, fsync, fdatasync

1. Sync调用时,只是告知kernel对所有的磁盘缓冲中修改过的页面要被调度写回磁盘,但sync返回时,并不意味着写操作已经完成。那样的话sync可能会等很长时间。

还有一个sync命令,他也会调用sync函数。

2. Fsync(int fd)只对一个file descriptor进行该操作,并且返回时,所有写操作已经完成。

3. fdatasync(int fd)只对一个文件的一部分数据进行该操作。

系统多用一个守护进程来定期调用sync

3.14 fcntl函数

#include

 

int fcntl(int filedes, int cmd, ... /* int arg */ );

Returns: depends on cmd if OK (see following), 1 on error

功能:

The fcntl function is used for five different purposes.

1Duplicate an existing descriptor (cmd = F_DUPFD)

2Get/set file descriptor flags (cmd = F_GETFD or F_SETFD)

3Get/set file status flags (cmd = F_GETFL or F_SETFL)

4Get/set asynchronous I/O ownership (cmd = F_GETOWN or F_SETOWN)

5Get/set record locks (cmd = F_GETLK, F_SETLK, or F_SETLKW)

 

1File descriptorflags中的close-on-exec flag: 我们在进程A中打开了文件f, 当文件ffile descriptorclose-on-exec flag被设置的时候,当我们执行exec系统调用时,进程A的代码段,数据段等都被新的程序代替,而且进程A中打开的文件也会被关闭。如果close-on-exec没有设置,在exec后,旧进程打开的文件就不会被关闭,即file descriptor依然有效,好处是一些daemon经常要fork然后exec一些子进程,这样如果不设置close-on-exec,这些子进程都会共享父进程的文件。

2File status flag包括:

O_RDONLY

open for reading only

O_WRONLY

open for writing only

O_RDWR

open for reading and writing

O_APPEND

append on each write

O_NONBLOCK

Non-blocking mode

O_SYNC

wait for writes to complete (data and attributes)

O_DSYNC

wait for writes to complete (data only)

O_RSYNC

synchronize reads and writes

O_FSYNC

wait for writes to complete (FreeBSD and Mac OS X only)

O_ASYNC

asynchronous I/O (FreeBSD and Mac OS X only)

 

例子:读取一个file descriptorstatus flag并打印出来。

$ ./a.out 0 < /dev/tty
     read only
     $ ./a.out 1 > temp.foo (输出被重定向到temp.foo中)
     $ cat temp.foo
     write only
     $ ./a.out 2 2>>temp.foo
     write only, append
     $ ./a.out 5 5<>temp.foo
     read write
 
上述例子的代码:
Figure 3.10. Print file flags for specified descriptor
#include "apue.h"
#include 
int
main(int argc, char *argv[])
{
 
    int       val;
 
    if (argc != 2)
        err_quit("usage: a.out ");
 
    if ((val = fcntl(atoi(argv[1]), F_GETFL, 0)) < 0)
        err_sys("fcntl error for fd %d", atoi(argv[1]));
 
    switch (val & O_ACCMODE) {
    case O_RDONLY:
        printf("read only");
        break;
 
    case O_WRONLY:
        printf("write only");
        break;
 
    case O_RDWR:
        printf("read write");
        break;
 
    default:
        err_dump("unknown access mode");
    }
 
    if (val & O_APPEND)
        printf(", append");
    if (val & O_NONBLOCK)
        printf(", nonblocking");
#if defined(O_SYNC)
    if (val & O_SYNC)
        printf(", synchronous writes");
#endif
#if !defined(_POSIX_C_SOURCE) && defined(O_FSYNC)
    if (val & O_FSYNC)
        printf(", synchronous writes");
#endif
    putchar('\n');
    exit(0);
}

Linux ext2不遵从O_SYNC的定义

O_SYNClinux ext2 file system上并不能起到作用,即如果以这个模式打开文件,我们调用write后,write返回后,并不能保证数据已经写到了磁盘上,而仅仅是将该数据放入了一个将要被写到磁盘上的队列中。因此对使用O_SYNC和不使用 O_SYNC打开的文件进行write操作,在耗时上没什么区别,这个我也测试过。

而使用sync(), sync(fd)的效果接近,即可以保证数据写到了磁盘上了。

#include

#include

#include

#define BUFFSIZE 4096

int main()

{

 

    int n=0;

    char buf[BUFFSIZE];

#if 0   

    int flags = fcntl( STDOUT_FILENO, F_GETFL, 0 );

    if( flags < 0 )

    {

           printf("get file STDOUT_FILENO flag error!\n ");

           return -1;

    }

    flags |= O_SYNC;

    int ret = fcntl( STDOUT_FILENO, F_SETFL, flags );

    if( ret < 0 )

    {

           printf("set flag error on file STDOUT_FILENO\n");

           return -1;

    }

#endif 

    while( (n = read( STDIN_FILENO, buf, BUFFSIZE )) > 0 )

    {

           if( write( STDOUT_FILENO, buf, n ) != n )

           {

                  printf("write error\n");

                  break;

           }

    }

//  fsync(STDOUT_FILENO);

//  sync();

    return 0;

}

上面代码中,使用#if 0包括的部分就是设置O_SYNC的代码段,是否设置O_SYNC效果是一样的。且fsync()sync()的效果也一样。不过都比O_SYNC耗时多。

3.15 ioctl 函数

Ioctl函数的操作可以分为几类:

Category

Constant names

Header

Number of ioctls

disk labels

DIOxxx

6

file I/O

FIOxxx

9

mag tape I/O

MTIOxxx

11

socket I/O

SIOxxx

60

terminal I/O

TIOxxx

44

3.16 /dev/fd/xxx

打开一个/dev/fd/n文件,如果该文件已经被打开,就类似于调用dup()。好处是,为stdio等提供了一个文件路径名的方式来定位。

阅读(1806) | 评论(0) | 转发(0) |
0

上一篇:3 file i/o -1

下一篇:c99 增加的restrict关键字

给主人留下些什么吧!~~