码迷,mamicode.com
首页 > 其他好文 > 详细

unix环境高级编程笔记(2)-- 文件I/O之不带缓冲的I/O

时间:2014-11-02 22:13:44      阅读:238      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   io   color   ar   os   使用   sp   

1 引言

  不带缓冲区的I/O(unbuffered I/o)是指每个read 和 write 都调用内核中的一个系统调用,这些不带缓冲区的I/O 不是ISO C 的组成部分。


2 文件描述符

  每个打开的文件都通过文件描述符引用,文件描述符是一个非负整数。open 和 create 函数返回的文件描述符供 read write 和 close 使用。

unix中文件描述符0与标准输入相关联,文件描述符1与标准输出相关联,文件描述符2与标准出错输出相关联。


 

3 不带缓冲区的I/O函数

下面介绍6个常用的I/O函数 open,creat,read,write,lseek,close.

3.1 open函数

#include <fcntl.h>
int open(const char *pathname,int oflag,.../* mode_t mode*/)
成功返回文件描述符,出错返回-1 
open函数返回的文件描述符一定是最小的未用的描述符数值。

对于open而言,只有创建新文件的时候才会用到第三个参数 mode

pathname是打开或创建文件的名字,oflag说明此函数的选项,由以下常量进行按位或构成oflag(这些常量定义在<fcntl.h>中)

必选:且只能选一个

       O_RDONLY                   只读打开                 

       O_WRONLY                  只写打开

       O_RDWR                      读 写打开

可选:

  O_APPEND      每次写操作都写在文件的尾端

  O_CREAT          若此文件不存在则创建它,使用此选项时,必须指定第三个参数 mode 用于指定该文件的访问位权限。

  O_EXCL        如果同时指定了O_CREAT,若此文件存在则出错返回 -1 用于测试一个文件是否存在,测试和创建新文件是一个原子操作

  O_TRUNC        如果此文件存在,而且为只写或者读写成功打开,则此文件截断为0.

  O_NOCTTY      如果pathname是终端设备,则不将此设备分配作为进程的控制终端

  O_NONBLOCK      如果pathname是一个FIFO,一个块特使文件,一个字符特殊文件,则此选项为本次打开操作及后续的I/O操作设置为非阻塞模式

下面三个标志也是可选的:

  O_DSYNC         每次写等待物理I/O完成,如果写操作并不影响读取刚刚写入的数据,则不等待文件的属性更新。

  O_RSYNC       是每一个以文件描述符作为参数的read操作等待,直至任何对文件同一部分进行的未决写操作完成。

  O_SYNC         使每次write都等待物理I/O操作完成,

O_DSYNC 在重写现有部分内容时,文件时间属性不会同步更新,而O_SYNC每次write操作都会在返回前等新文件时间。

3.2 creat函数

#include <fcntl.h>
int creat(const char *pathname,mode_t mode)
若成功返回以只写方式打开的文件描述符,失败返回 -1

现在可以用以下方式调用open来代替creat

open(pathname,O_WRONLY   |  O_CREAT  |  O_TRUNC,mode);

3.3 close函数

#include <fcntl.h>
int close(int filedes);
若成功返回0,出错返回 -1 ;

当一个进程终止时,会自动关闭所有打开的文件描述符,所以很多程序利用这一功能不显示调用close关闭文件描述符;

3.4 lseek函数

#include <unistd.h>
off_t lseek(int filedes,off_t offset,int where);
成功返回新的文件偏移量,出错返回 -1 ;

 offset 的含义与where的选择有关:

  SEEK_SET    将文件偏移量设定为距文件开始处offset个字节;

  SEEK_CUR    将文件偏移量设定为当前值加上offset (offset可正可负);

  SEEK_END    将文件偏移量设定为文件长度加上offset(offset可正可负);

调用lseek(fd,0,SEEK_CUR)可以确定打开文件的当前偏移值。也可以用此来测试文件是否可以设置偏移量。若fd为管道,FIFO,和网络套接字 则返回 -1,并将errno设为ESPIPE;

#include <stdio.h>
#include <unistd.h>
int main()
{
    if(lseek(STDIN_FILENO,0,SEEK_CUR) == -1)
        printf("connot seek\n");
    else
        printf("seek OK\n");
    return 0;
}

编译该程序,运行。

root@debian:/program# ./3-1 < /etc/motd
seek OK
root@debian:/program# cat < /etc/motd | ./3-1
connot seek

3.4.1 具有空洞的文件

当文件偏移量大于当前文件长度时候,就在文件中形成一个空洞,位于文件中但没有写过的字节都被读为0。

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#define FILE_MODE S_IRUSR | S_IWUSR | S_IXUSR
int main()
{
    char buf1[] = "abcde";
    char buf2[] = "ABCDE";
    int fd;
    if((fd = creat("foo",FILE_MODE)) < 0)
    {
        printf("creat file error\n");
        return -1;
    }
    if(write(fd,buf1,5) != 5)
    {
        printf("write error\n");
        return -1;
    }
    if(lseek(fd,1024,SEEK_SET) == -1)
    {
        printf("seek error\n");
        return -1;
    }
    if(write(fd,buf2,5) != 5)
    {
        printf("write error\n");
        return -1;
    }
    return 0;
}
查看文件大小
root@debian:/program# ls -l foo -rwx------ 1 root root 1029 Nov 2 20:48 foo root@debian:/program#
查看文件内容

root@debian:/program# od -c foo
0000000   a   b   c   d   e  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
0000020  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
*
0002000   A   B   C   D   E
0002005
root@debian:/program# 

可以看出文件中未写的字节全部填充为0.

3.5 read函数

#include <unistd.h>
ssize_t read(int filedes,void *buf,ssize_t nbytes);
若成功返回读取到的字节数,若已到达文件末尾返回0,出错返回-1;

读操作从当前的文件偏移量开始,在read返回前,文件偏移量将增加实际读取的字节数。实际读取的字节数可能比nbytes小。

3.6 write函数

#include <unistd.h>
ssize_t write(int filedes,const void *buf,size_t nbytes);
若成功返回写入的字节数,一般返回值等于nbytes,出错返回 -1;

对于普通文件,write操作从文件的当前偏移量处开始,如果打开文件时制定了O_APPEND,则将文件偏移量设置为文件的结尾处,成功写之后,文件偏移量将增加写的字节数。

 

/*将标准输入复制到标准输出*/
#include <stdio.h> #include <unistd.h> #define BUFFSIZE 1024 int main() { int n; char buf[BUFFSIZE]; while((n = read(STDIN_FILENO,buf,BUFFSIZE)) > 0) if(write(STDOUT_FILENO,buf,n) != n) { printf("write error\n"); return -1; } if(n < 0) printf("read error\n"); return 0; }
root@debian:/program# ./3-3
hello world!
hello world!

 

unix环境高级编程笔记(2)-- 文件I/O之不带缓冲的I/O

标签:des   style   blog   io   color   ar   os   使用   sp   

原文地址:http://www.cnblogs.com/avengervirus/p/4069111.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!