Linux中缓存IO的概念:
   
缓存IO机制中,操作系统会将 I/O 的数据缓存在文件系统的页缓存( page cache )中 ,IO输入输出的数据会先被拷贝到操作系统内核的缓冲区中,然后才会从操作系统内核的缓冲区拷贝到应用程序的地址空间。
    这种机制的
    
     优点
    
    显而易见:
   
- 
     缓存 I/O 使用了操作系统内核缓冲区,在一定程度上分离了应用程序空间和实际的物理
 
 设备
- 
     因为我们的数据被缓存到了页缓存中,所以缓存 I/O 可以减少读盘的次数,直接从页缓存中获取数据,从而提高性能。
 
 
 缺点
 
 :
不能直接在应用程序地址空间和磁盘之间进行数据传输 ,数据拷贝操作所带来的 CPU 以及内存开销是非常大。
Linux系统调用中关于文件的操作,需要包含一些头文件:
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
这些头文件中包含了打开,关闭,创建,读文件,写文件的函数,还有标志位,以及一些宏变量定义。具体需要包含的头文件可以使用man查找帮助。
    
    
    1、文件描述符
   
    文件描述符是一个非负整数。当打开一个现存文件或创建一个新文件时,内核向进程返回一个文件描述符。当读、写一个文件时,用
    
     open
    
    或
    
     creat
    
    返回的文件描述符标识该文件,将其作为参数传送给
    
     read
    
    或
    
     write
    
    。
   
    
    
    2、open函数
   
open函数存在两个函数原型,
函数原型1:
int open(const char *pathname, int oflag) ;
返回值:若成功为文件描述符,出错返回-1
    参数说明:
    
     pathname
    
    即为需要打开的文件名,可以包含文件路径
   
    
     oflag
    
    参数可用来说明此函数的多个选择项。用下列一个或多个常数进行或运算构成
    
     oflag
    
    参数(这些常数定义在< fcntl.h >头文件中):
   
- 
     
 O_RDONLY
 
 只读打开。
- 
     
 O_WRONLY
 
 只写打开。
- 
     
 O_RDWR
 
 读、写打开。
 
 上面的这三个参数是打开方式,只指定一个。
 
 还可以搭配下面的参数:
- 
     
 O_APPEND
 
 追加到文件末端。
- 
     
 O_TRUNC
 
 如果此文件存在,而且为只读或只写成功打开,则将其长度截短为 0。
- 
     
 O_CREAT
 
 若此文件不存在则创建它。使用此选择项时,需同时说明第三个参数
 
 mode
 
 ,用其说明该新文件的存取许可权位。
- 
     
 O_EXCL
 
 如果同时指定了
 
 O_ CREAT
 
 ,而文件已经存在,则出错。这可测试一个文件是
 
 否存在,如果不存在则创建此文件成为一个原子操作。
 
 例如,使用
 
 open
 
 函数创建并打开一个文件:
int open(pathname, O_RDWR|O_CREAT|O_TRUNC, mode) ;
函数原型2:
int open(const char *path, int oflags,mode_t mode);
当我们使用open打开并且创建一个不存在的文件时才会使用原型2,mode参数是为创建的文件添加的权限,可以取值如下:
     
   
    其实也可以使用数字组合作为
    
     mode
    
    的值,使用
    
     0777
    
    即为赋予全部权限。
   
    
    
    3、creat函数
   
    创建一个新文件
    
    函数原型:
   
int creat(const char *pathname, mode_t mode) ;
参数说明:
    
     mode
    
    文件的权限,具体可以参考
    
     open
    
    函数。
   
返回值:若成功为文件描述符,出错返回-1
    
    
    4、close函数
   
    关闭一个已经打开的文件
    
    需要包含
    
     #include <unistd.h>
    
    头文件,原型:
   
int close (int filedes);
    返回:若成功为 0,若出错为- 1
    
    
     filedes
    
    为已打开的文件描述符。
   
    
    
    5、lseek函数
   
    
     lseek
    
    函数可以设置当前文件位移量,定位打开的文件。原型:
   
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int filedes, off_t offset, int whence) ;
    返回:若成功为新的文件位移,若出错为- 1。
    
    
     filedes
    
    为文件描述符
    
    
     offset
    
    为偏移量吗,与
    
     whence
    
    相关
    
    
     whence
    
    说明:
   
    • 若whence是
    
     SEEK_SET
    
    ,则将该文件的位移量设置为
    
     距文件开始处
    
    offset 个字节。
    
    • 若whence是
    
     SEEK_CUR
    
    ,则将该文件的位移量设置为
    
     其当前值加offset
    
    , offset可为正或负。
    
    • 若whence是
    
     SEEK_END
    
    ,则将该文件的位移量设置为
    
     文件长度加offset
    
    , offset可为正或负。
   
    
    
    6、read函数
   
read函数从打开的文件中读数据。
ssize_t read(int fd,void *buf,size_t len)
参数说明:
    
     buf
    
    :读取文件后存放数据的地址
   
len:读取的字节大小
返回值:读到的字节数,若已到达文件尾,返回0;出错返回-1。
    
    
    7、write函数
   
 ssize_t write(int fd,const void *buf,size_t count)
参数说明:
    
     buf
    
    :为需要写入数据
   
    
     count
    
    :写入的数据的大小,单位字节
   
    
     返回值
    
    :若成功返回已写的字节数,出错返回-1。
   
综合代码示例:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
char buf[] = "hello file!";
char buf1[] = "set offset!\n";
int main(int argc, char **argv)
{
    int i;
    int fd;
    if(argc<2)
    {
        printf("no filename to creat!");
    }
    else 
    {
        for(i=1;i<argc;i++)
        {
            if((fd=open(argv[i], O_CREAT|O_RDWR, 777))==-1)
            {
                printf("creat %s failed!\n",argv[i]);           
            }
            else 
            {
                printf("%s creat success!\n",argv[i]);
                if(write(fd, buf, sizeof(buf))>=0)
                {
                    printf("write success!\n");
                    if(lseek(fd, 20, SEEK_SET)>=0)
                    {
                        printf("set offset success!\n");
                        if(write(fd, buf1, sizeof(buf1))>=0)
                        {
                            printf("rewrite success!\n");
                        }
                        close(fd);
                    }                   
                }else{
                    printf("write failed!\n");
                }
            }
        }    
    }
    exit(0);
}
    根据main函数传入的参数,先
    
     open
    
    创建并以读写方式打开一个文件,创建成功后写入
    
     "hello file!"
    
    ,然后
    
     lseek(fd, 20, SEEK_SET)
    
    设置当前文件偏移量距开始处20,再次写入
    
     set offset success!\n
    
    ,结果如下:
    
    
    
    可以看到已经生成了hello.c和a.txt了,内容与我们期望的一致,在开头偏移20处写入了
    
     set offset!\n
    
    。
    
    
    
    hello.c和a.txt写入的内容完全一致。
    
     
   
示例2,简单的创建文件并且进行读写:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
char *test_string = "import me!\n";
//不能使用字符串常量,否则无法读出数据存入buf
char user_buf1[] = {0};
char user_buf2[]= {0};
int main(int argc, char *argv[])
{
    int fd1, fd2;
    int count;
    int size;
    
    printf("sizeof(test_string) = %d\n", (int)sizeof(test_string));
    printf("strlen(test_string) = %d\n", (int)strlen(test_string));
    /*/home/boy/Unix/*/
    if((fd1 = creat("main.py", 0777)) != -1)
    { 
        count = write(fd1, test_string, 11);//sizeof(test_string)
        if(count < 0)
        {
            printf("write main.py failed!\r\n");
            return -1;
        }
        //close(fd1);
        printf("write main.py success!\n");
        fd1 = open("main.py", O_RDWR); //需要再次打开文件才能读 
        if((count = read(fd1, user_buf1, 11)) == -1)
        {
            printf("read main.py failed!\r\n");
            return -1;
        }
        printf("userbuf1 = %s\n", user_buf1);
        close(fd1);
   } 
   if((fd2 = open("haha.c", O_RDWR | O_CREAT, 0777)) > 0)
   {
        printf("haha.c creat success!\n");
        if((count = read(fd2, user_buf2, sizeof("hello file\n")) < 0 ))
        {
            printf("read haha.c failed!\n");    
            return -1;
        }
        printf("user_buf2 = %s\n", user_buf2);
        close(fd2);
   }
   exit(0);
}
    首先从文件
    
     creat
    
    创建文件
    
     main.py
    
    ,然后向其写入,写入之后需要重新打开,才能进行读操作,获取文件内容进行验证,接着打开已经存在的文件
    
     haha.c
    
    ,读取文件内容,进行验证,haha.c内容如下:
   
     
   
执行结果:
     
   
 
