Linux学习之IO

     Linux中的IO可分为三类:文件IO、标准IO和目录IO。

 
一、文件IO(系统调用函数)
    是直接调用内核提供的系统调用函数,头文件是unistd.h
   1)open — 打开或创建一个文件
      open(char *,flag,mode)在fcntl.h文件中声明
      函数作用:创建或打开某个文件
      参数: char*   包含有文件名和路径
                 flag     打开文件的方式(只读,只写,读写)
                 mode  创建文件的权限
      flag内容如下:
              O_RDONLY:只读
              O_WRONLY:只写
              O_RDWR:读写
              O_CREAT:创建一个文件
              O_EXCL:如果使用O_CREAT时文件存在,则可返回错误消息,这一参数可测试文件是否存在
              O_TRUNC:打开文件(会把已经存在的内容删除)
              O_APPEND:追加方式打开文件(不会把已经存在的内容删除)
      返回值:成功:文件描述符,它是一个非负的正整数,即文件的ID号
                   出错:-1
      文件描述符:内核映射到用户程序的文件ID号 
      ID号的规律:从0开始累加
        程序进行时(进程),内核会自动打开3个文件描述符,0,1,2,分别对应,标准输入、输出和出错。这样在程序中,每打开一个文件,文件描述符值从3开始累加。
      open函数创建的权限是:
        ==mode & (~umask)
        例:111 111 111B & ~(000 010 101B) = 111 101 101B
     
   2)write(int fd,void *buf,size_t count)
         第一个参数:向哪一个文件中去写
         第二个参数:向这个文件中写什么内容
         第三个参数:向这个文件中写多少个
         返回值:是实际写的字节数
   3)read(int fd,void *buf,size_t count)
        第一个参数:从哪一个文件里去读
        第二个参数:读到什么地方去
        第三个参数:读多少个
        返回值:实际读的字节数
   4)lseek(int fd,off_t offest,int whence)   
       作用:调整读写的位置指针
       该函数的头文件:sys/types.h ,unistd.h
       第一个参数:要调整的文件的文件描述符
       第二个参数:偏移量,每一次读写操作所需要移动的距离,单位是字节的数量,可正可负(向前移,向后移)
       第三个参数:当前位置的基点,有三个标志:
                          SEEK_SET:当前位置为文件的开头,新位置为偏移量的大小。
                          SEEK_CUR:当前位置为文件指针的位置,新位置为当前位置加上偏移量
                          SEEK_END:当前位置为文件的结尾,新位置为文件的大小加上偏移量的大小
       返回值:成功:文件当前的位置
                    出错:-1
二、标准IO(C库函数)
     是间接调用系统调用函数,头文件是stdio.h
   
     三个缓存的概念(数组)
     1)、每个程序中的缓存,就是用户想从内核读写的缓存(数组)——用户空间的缓存
     2)、每打开一个文件,内核在内核空间中也会开辟一块缓存 —— 内核空间缓存
            文件IO中的写即是将用户空间中的缓存写到内核空间的缓存中
            文件IO中的读即是将内核空间的缓存写到用户空间的缓存中
     3)、标准IO的库函数中也有一个缓存 —— 库缓存
      文件IO                                                  标准IO
       open                                                       fopen
       close                                                       fclose
       lseek                                                       fseek,rewind
       read                                                        读写函数比较多(分全缓存、行缓存和无缓存)
       write
      1)、FILE *open(const char *path,const char *mode)
            返回值:FILE*   文件流指针 —— 类似于文件IO中的文件描述符
            FILE 定义:struct_IO_FILE,在/usr/include/libio.h,包含读写缓存的首地址、大小、位置指针等。
            标准的输入流:stdin    0
            标准的输出流:stdout  1
            标准出错流:    stderr  2
       2)、三类读写函数
             一类:行缓存 ——遇到新行符(\n)或写满缓存时,即调用系统调用函数将库函数写到内核
                      读:fgets,gets,printf,fprintf,sprintf
                      写:fputs,puts,scanf
                   一个字符:
                      读:fgetc,getc,getchar
                      写:fputc,putc,putchar
             二类:无缓存 —— 只要用户调用这个函数,就会将其内容写到内核中
             三类:全缓存 —— 只有写满缓存才调用系统调用函数
                      读:fread
                      写:fwrite
        3)、fclose()
              包含fflush()函数
              调用成功返回0, 失败返回EOF,并设置errno
              在该文件被关闭前,刷新缓存中的数据。如果标准IO库已经为该流自动分配了一个缓存,则释放此缓存
        4)、刷新缓存函数:fflush(FILE *fp)
              把库函数中的缓存的内容强制写到内核中
        5)、无缓存:stderr
        6)、调整读写位置指针函数:
                fseek()参数与lseek()一样,但返回值不一样
                       lseek()的返回值是:当前文件的位置指针值
                       fseek()的返回值是:成功返回0,失败返回-1
                rewind(FILE *fp)用于设定流的文件位置指示为文件开始,该函数调用成功无返回值。
                       rewind()等价于(void)fseek(fp,0,SEEK_SET)
                ftell(FILE *fp) 用于取得当前文件位置,调用成功则为当前文件位置指示,出错为-1。
        7)、行缓存的读写函数gets和puts
            gets与fgets的区别:
                gets()不能指定缓存的长度,这样可能造成缓存越界(若该行长度大于缓存长度),写到缓存之后的存储空间中,从而产生不可预料的后果。
                gets()只能从标准输入中读
                gets()并不将新行符存入缓存中,fgets()将新行符存入缓存中
            puts与fputs的区别:
                puts()只能向标准输出中写
                puts()输出时会添加一个新行符,fputs()不会添加。
        8)、fprintf、printf、sprintf
               int fprintf(FILE *stream,“字符串格式”)
                    fprirntf 可以输出到文件中,也可以输出到显示器
                    printf  只能输出到显示器中
               int sprintf(str*,“字符串格式”)
                    输出内容到一个字符串中
        9)、一个字符读写函数fgetc和fputc
               int fgetc(FILE *fp)     ——>不是行缓存函数
                    功能:从文件中读取一个字符
                    返回值:正确为读取的字符,到文件结尾或出错则返回EOF
               int fputc(int c,FILE *fp)   ——>有缓存,但不是行缓存函数
                    功能:写一个字符到文件中
                    返回值:成功则返回输入的字符,出错返回EOF
        10)、int feof(FILE *stream)
                    功能:判断是否已经到文件结束
                    返回值:到文件结束,返回为非0,没有则返回0
        11)、int ferror(FILE *stream)
                    功能:判断是否读写错误
                    返回值:是读写错误,返回为非0,不是则返回0
        12)、void clearerr(FILE *stream)
                    功能:清除流错误
          memset(char *str,int n,int length)//清缓存函数       
        13)、全缓存的读写函数:fread和fwrite
               size_t fread(void *ptr,size_t size,size_t nmemb,FILE *stream);
               size_t fwrite(const void *ptr,size_t size,size_t nmemb,FILE *stream);
               参数:ptr —— 写的内容
                        stream —— 写到哪里去
                        size —— 写的内容中,每一个单元所占的字节数
                        nmemb —— 写的内容中,有多少个单元数
               总的字节数:size*nmemb
               返回值:实际读写的单元数  
三、Linux操作系统标准IO支持的函数库
      1、静态库:libxxx.a,在编译时就将库编译进可执行程序中。
                     优点:程序的运行环境中不需要外部的函数库。
                     缺点:可执行程序大
      2、动态库:又称共享库,libxxx.so,在运行时将库加载到可执行程序中
                     优点:可执行程序小
                     缺点:程序的运行环境中必须提供相应的库
           函数库目录:/lib   或   /usr/lib
      3、静态库的制作:
             1)、将源文件生成目标文件:gcc -c -o file.o file.c
             2)、静态函数库创建命令 :ar
                     ar -cr -o libfile.a file.o
                      -cr:表示当插入的模块file.o已经存在libfile.a中,则覆盖;反之ar显示一个错误消息
             3)、如果从别处得到一个静态库libunknown.a,想知道其中包含哪些模块
                    用命令:ar -t libunknown.a
             4)、静态库的编译:gcc -o main.c -L. -lfile(编译main.c就会把静态函数库整合进mian)
                   其中:-L 指定静态函数库的位置供查找,L后面有“.”,表示静态函数库在本目录下查找
                             -l 指定了静态函数库名,由于静态函数库的命名方式是lib***.a,其中的lib和.a忽略
             5)、运行:./a.out
       4、动态库的制作:
              1)、生成目标文件:gcc -c -o file.o file.c
              2)、动态函数库创建命令:
                    gcc -shared -fpic -o libsub.so file.o
                     -fpic:产生位置无关代码
                     -shared:生成共享库
              3)、动态库编译:gcc -o main.c -L. -lsub
                   此时不能立即./a.out,因为在动态函数库使用时,会查找/usr/lib   /lib目录下的动态函数库,而此时程序生成的库不在里面。 
              4)、方法一:将 libsub.so放到/usr/lib或lib中再运行./a.out
                    方法二:环境变量方法
                                 假设libfile.so的路径是/home/my_project/c
                           执行命令:export LD_LIBRARY_PATH=/home/my_project/sub
                           再执行./a.out即可得到结果

没有学到函数库这一节的时候,总以为VI下的C语言分文件编写和windows下的编译环境是一样的,但试了之后,结果相当惨,当时懒得没有自己查,因为当时用ubuntu的时候也不多,现在确实是学到了,区别还是相当大的。
四、目录IO       
       1、两个头文件:#include "sys/types.h"
                               #include "dirent.h"
       2、opendir  ——  只能打开目录
            mkdir —— 创建目录
            readdir —— 读目录
            rewinddir —— 调整位置指针
            telldir —— 返回位置指针所在的位置
            seekdir —— 调整位置指针到任何地方
            closedir —— 关闭目录        
                   

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值