IO操作总结及系统调用IO函数的使用(open....)

239 篇文章 12 订阅

一、前言

参考书《unix高级环境编程》

IO操作分为:

(文件IO)标准IO:stdio  返回值是FILE*

系统调用IO:sysio(文件IO) 返回值是int  fd 文件描述符

注:当二者都能用的情况下,优先使用标准IO

解释:标准IO是依靠系统IO实现的(是将系统IO进行了封装),但是如果平台不一样(如windows或linux)系统IO就不同,标准IO则解决了跨平台的问题(比如,都是#include <stdio>,printf则windows或linux下都能使用)

(比如,stdio中fopen 在windows下依赖openfile,在linux下依赖open)所以,标准IO的移植性好。

文件IO中,是通过FILE*这个结构体指针来操作的。

系统IO中,也有一个类似FILE的结构体(每次打开文件都会产生一个结构体-关联文件的属性),但是又将该结构体的首地址放在了一个数组(该数组存在于进程空间中)中,这个数组的下标就是文件描述符,故文件描述符是从0开始的

默认情况下,该数组的大小为1024;故最大打开的文件个数为1024;(可以通过ulimit -a 来查看,再通过对应的参数来修改对应属性 ulimit -参数 )

stream流stdin------对应0文件描述符

stream流stdout------对应1文件描述符

stream流stderr-------对应2文件描述符

文件描述符fd总是优先使用当前可用的最小的文件描述符。

cache:是读的缓冲区,读内容先读到cache中,是读的加速机制

buffer:是写的缓冲区,写内容先写到buff中,是写的加速机制

阻塞:以读为例,读读,没的读了,卡在这,直到有东西读了;

非阻塞:以读为例,读读,没的读了,干别的去了,尝试做,如果读不了,则去干别的或者回头再来读,不在这死等;

二、系统调用函数:

1)open//-------fopen是通过该函数封装

#include <sys/types.h>
#include <sys/stat.h>

#include <fcntl.h>

int open(const char *pathname,flags);

flags:是个位图,必须包括:

  • O_RDONLY,
  • O_WRONLY,
  • O_RDWR.

还可以添加的创建选项或状态选项:,通过或的方式与必选的3个连用

  • O_CREAT:创建
  • O_TRUNC:截断,截短
  • O_EXCL:必须打开一个新的文件,如果当前打开的是已存在的文件时,则报错,故跟O_CREAT联用。
  • O_APPEND:追加模 式
  • O_NONBLOCK:非阻塞,只要不加这个,默认的就是阻塞

         标准IO与系统IO权限对应的权限。

          r--->对应 O_RDONLY

          r+----》对应O_RDWR

         w---->对应O_WRONLY|O_CREAT|O_TRUNC   //只写;如果文件不存在创建;如果文件存在,则截断

         w+----->对应0_RDWR|O_CREAT|O_TRUNC 

 

成功:返回文件描述符

失败:返回-1,设置errno.因为成功的话,返回的文件描述符是数组的下标,而下标是从0开始的。

 注意:c语言中的同名open,表示这个函数是个变参函数,形如printf;

当flags中有 O_CREAT时,要用到三参数的open,因为此时需要通过mode参数指定所创建文件的权限。

无O_CREAT则用两参的open.

mode给的权限后,实际的权限是按照权限公式mode & ~umask   //比如   0666 & ~umask 

2)close//fclose是通过该函数封装

int close(int fd);// 用来关闭文件描述符,一般不判断返回值,因为,我们认为close不会出错。

3)read//文件IO中的读操作都是使用该函数封装

#include <unistd.h>

ssize_t read(int fd,void*buf,size_t count);

从fd中读count个字节到buf中。

返回值:

>0:返回读到的字节数//注:返回值会小于count

=0:表示到文件尾了,没有内容可读了。

<0:读错误,设置errno.

4)write//文件IO中的写操作都是使用该函数封装

#include <unistd.h>

ssize_t write(int fd,const void*buf,size_t count);

从buf中的count个字节写到fd中。

返回值:

>0:返回写成功的字节数//注:返回值会小于count

=0:表示什么都没写进去//原因:遇到假的错误

<0:写错误,设置errno.

5)lseek//fseek是通过该函数封装

#include <sys/types.h>

#include <unistd.h>

off_t lseek(int fd,off_t offset,int whence);

定位文件位置指针。

返回值:从文件开始位置到当前位置字节数//当前位置,其实也是ftell的作用

故:lseek可以理解为是将fseek与ftell的综合体。

 

例子:

#include <stdip.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#incldue <fcntl.h>
#define BUFSIZE 1024
int main(int argc,char** argv)
{
    int sfd,dfd;
    int len,ret,pos = 0;
    char buf[BUFSIZE];
    if(argv<3)
    {
        fprintf(stderr,"arg error...\n");
        exit(1);
    }
    sfd = open(argv[1],O_RDONLY);
    if(sfd<0)
    {
         perror("open");
         exit(1);   
    }
    dfd = open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0600);//有O_CREAT属性,一定要用三参函数,并设置权限。
    if(dfd<0)
    {
         close(sfd);//一定要关闭原文件,防止内存泄露
         perror("open");
         exit(1);   
    }
    while(1)
    {
        len = read(sfd,buf,BUFSIZE);
        if(len<0)
        {
            perror("read");
            break;
        }
        if(len==0)
        {
            break;
        }
        //len>0的情况
        while(len>0)
        {
            ret = write(dfd,buf+pos,len);
            if(ret<0)
            {
                perror("write");
                exit(1);
            }
            len -= ret;
            pos += ret;
         }
        
        }
       
    }
    
    close(sfd);//先关闭原文件
    close(dfd);//后关闭目标文件




}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值