【UNIX】什么是IO以及文件IO

I/O输入/输出(Input/Output),分为IO设备和IO接口两个部分.。

与IO性能直接相关的几个缓存分别是文件系统缓存(File SySTem Cache)、磁盘控制器缓存(Disk CONtroller Cache)和磁盘缓存(Disk Cache,也称为Disk Buffer)。

不管是控制器缓存还是磁盘缓存,他们所起的作用主要是分为三部分:缓存数据、预读(Read-ahead)和回写(Write-back)。

什么是文件的概念:就是一组相关数据的有序集合,而文件名就是这组数据集合的名称。

一般常规文件有ASCII码文件还有就是二进制文件还有包括目录和字符设备,块设备,有名管道,套接口,和符号链接;

在说明文件IO和标准IO的区别之前

先了解到的是在UNIX操作系统下的出错处理:

首先了解的是全局出错码errno,它的头文件是<errno.h>,它返回的是字符串格式输出,那么打印格式就是printf("%s\n",error);

还有一种打印方法,即perror("this is "),这是一种简化形式,他会自己自动补上是成功读取还是失败。它的输出格式是双引号里的字符(字符自己打的)后面会默认加上:冒号还有输出的出错信息和成功信息。

【1】文件IO

                  文件IO是直接对应内核的系统调用。

当一个文件IO(读写)要对磁盘的数据访问读写输入输出的时候,内核系统会保护硬件,从而会在内核空间创建文件描述符,内核向进程返回一个文件描述符,他表示硬件设备文件在内存空间的映像。

文件IO不带缓冲,指的是每个read和write都是调用内核中相应的系统调用,不带缓存的文件IO不是ANSI的一部分,但是是POSIX的一部分,都经过标准的API。

对于常用的文件IO函数有;open read write close lseek以及creat函数(是open函数的一层封装):

对于open函数有几种形式,一般形式如下:

#include
   
   
    
    
#include
    
    
     
     
#include
     
     
      
      
#include
      
      
       
       

int main ()
{
    int fd;
    
    fd = open ("/home/tmp/text.c",
                O_RDONLY|O_WRONLY|O_RDWR|
                O_CREAT|O_APPEND,0777):
    if (fd == -1){
        perror("can not open");
        return -1
    }else{
        return 0
    }
    
                    
}
    //这里RD,WR,RDWR三种形式只有有一种形式出现就可以,他们是互斥关系
    //对于CREAT表示打开的文件不存在可以以创建的形式打开,但是后面要加权限位0777
    //,等其他权限,而APPEND是决定以什么方式创建文件的还有一种形式就是以清零
    //的形式O_TRUNC

example 2
#include
       
       
         #include 
        
          #include 
         
           #include 
          
            #include 
           
             #define lockfile "/etc/tmp" int main () { int fd; if (fd = open (lockfile,O_RDWR|O_CREAT|O_TRUNC,0644) == -1) { fprintf(stderr,"%d\n",errno); return -1; } } 
            
           
          
         
       
      
      
     
     
    
    
   
   
其中标志以什么方式打开形式是int flags有O_RDWR,O_CREAT。

return的成功返回时0,错误返回时-1。

当一个进程结束时,该进程打开的所有文件有内核来关闭,或者用close来关闭,

关闭一个文件的同时,也释放该进程加在该文件的所有记录锁。

设备文件一般都可以用OPEN函数打开,但不可以创建/dev下面的设备文件,但可以用mknod创建设备的节点

就在open()函数结束时加close(fd);


使用read()函数可以对已经打开的函数进行读取,read函数的一般形式是:

#include
   
   
    
    
#include
    
    
     
     

#define N 100

int main ()
{
    char buf[N];
    size_t nbytes;
    ssize_t bytes_read;
    int fd;
    
    nbytes = sizeof(buf);
    
    fd = open ("/tec/tmp",O_RDWR|O_CREAT,0644);
    if (fd == -1)   return -1;
    bytes_read = (fd,buf,nbytes);
    
    return 0;
    
}

/*
*这里的buf是应用程序所开的缓存空间大小,表示这个程序进程执行的时候一次可以读出
*多少数据,而nbytes则是内核文件描述符在内存空间给定进程空间大小,
*所以count的值要比buf大,
*当程序成功读出字节数就是read的返回值,在读操作的当前位移处开始,内核里记录
*了偏移量,buf是由调用者在内存空间创建缓存区的大小,并在使用后由使用者释放
*
*
*/

    
    
   
   
使用write()函数可以对一个打开的文件进行写操作:

这里读操作和写操作基本差不多,只是write函数也可以对read函数的写。


文件IO的lseek函数可以记录显示定位一个已经打开的文件

每当一个文件打开,都有一个与其相关的“当前文件偏移量”来记录下次文件从什么地方开始执行,在成功读写后,内核会自动维护偏移量并记录在内核中,标记下次程序从什么地方开始lseek只对常规文件静态文件有效,而对于那些流式文件则会失效,因为流式文件在内核中没有固定的pc标记读取的位置

这里可以间接求取文件大小;length =lseek (fd,0,seek_end);这里的0零时位置偏移量off_t offset。


文件偏移量可以大于文件当前长度,即是大于文件字节数但是不占用文件的空间,这样对文件的写操作会形成空洞。


修改于【2014-11-23-10:15】


【1】对于一个应用程序当要访问磁盘上的文件时,内核会帮应用程序打开文件,通过文件描述符来引用,在内存中创建磁盘上相应的文件内容,内核会向进程返回一个文件描述符,当读文件描述符的时候通过返回的文件描述符来标识文件,之后再将标识文件作为参数返回给read和write,这里的读写操作都是在内存中完成的,并没有改变磁盘上的文件,只有当进程结束后,uinx系统会通过shell关联幻术0,1,2,才可以正真意义上对磁盘文件永久的改写。


【2】对于lseek(当前文件偏移量):文件偏移量是由内核空间来维护的,当一个读写操作进程的时候,内核会自动记录当前位置,以便于下次读写继续从此处开始进行,但是人为也可以对lseek进行修改,当文件偏移量大于文件的字节数的时候,在写操作的时候,会形成空洞,这一点是可以允许的,对于文件中没有写过的字节都可以用0来存储,这只是在内存抽象的文件描述符引用的文件上修改的,当一个进程结束时,空洞并不占用磁盘上的存储区,对于新写的数据需要分配空间,但对于原文件尾部和新写的中间不需要分配磁盘空间。












评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值