linux基础IO

fopen fread fwrite fseek fclose

  1 /*回顾标准库IO接口*/
  2 
  3 #include <stdio.h>
  4 #include <string.h>
  5 
  6 int main()
  7 {
  8     FILE *fp = NULL;
  9     fp = fopen("./tmp.txt", "w+");
 10     if (fp == NULL) {
 11         perror("fopen error");
 12         return -1;
 13     }
 14 
 15     char buf[1024] = "jintianrenhaoshao~~\n";
 16     //size_t fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream);
 17     //返回值为 nmemb而不是size
 18     fwrite(buf, strlen(buf), 1, fp);
 19 
 20     //int fseek(FILE *stream, long offset, int whence);
 21     //对fp文件读写位置从whence开始偏移offset个字节
 22     //  whence: 
 23     //      SEEK_SET    从文件起始位置开始偏移    
 24     //      SEEK_CUR    从当前读写位置开始偏移
 25     //      SEEK_END    从文件末尾位置开始偏移
 26     //  返回值:从文件起始位置到当前跳转位置的偏移量
 27     fseek(fp, 0, SEEK_SET);
 28     //size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
 29     memset(buf, 0x00, 1024);
 30     int ret = fread(buf, 1, 1023, fp);
 31     if (feof(fp)) {
 32         printf("at end of file\n");
 33     }else  {
 34         perror("fread error");
 35     }
 36     printf("ret:%d--buf:[%s]\n", ret, buf);
 37     fclose(fp);
 38     return 0;
 39 }

 文件结构体

struct FILE
{
    char *_ptr;//文件输入的下一个位置
    int _cnt;//当前缓冲区的相对位置
    char *_base;//指基础位置(文件的起始位置)
    int _flag;//文件标志
    int _file;//文件的有效性验证
    int _charbuf;//检查缓冲区状况,如果缓冲区则不读取
    int _bufsiz;//文件的大小
    char *_tmpfname;//临时文件名
};

文件描述符:

进程通过struct file_struct 结构体来描述打开的文件----------------------使用struct file*  fd_array[],文件描述符就是数组的下标

用户打开文件,操作系统通过file结构体描述文件,并将指针添加到fd_array[]中。向用户返回这个文件描述信息在数组下标中的位置,用户操作文件的时候,将下标床给操作系统,系统通过下标找到文件

进程的描述符是有上限的

文件描述符的分配原则:最小未使用原则

一个进程在运行起来默认会打开三个文件:

  • 标准输入   0(文件描述符)  stdin(文件流指针)
  • 标准输出   1(文件描述符)  stdout(文件流指针)
  • 标准错误   2(文件描述符)  stderr(文件流指针)
  1 /*系统调用接口使用*/
  2 
  3 #include <stdio.h>
  4 #include <unistd.h>
  5 #include <string.h>
  6 #include <fcntl.h>
  7 
  8 int main()
  9 {
 10     //mode_t umask(mode_t mask);
 11     //设置调用进程的文件创建权限掩码
 12     umask(0);
 13     //int open(const char *pathname, int flags, mode_t mode);
 14     //  pathname:  要打开的文件路径名
 15     //  flags: 选项参数
 16     //      必选其一:
 17     //          O_RDONLY    只读
 18     //          O_WRONLY    只写
 19     //          O_RDWR      读写
 20     //      可选项:
 21     //          O_CREAT     文件存在则打开,不存在则创建
 22     //          O_TRUNC     将文件长度截断为0(清空原有内容)
 23     //          O_APPEND    追加
 24     //  mode:   权限 0664
 25     //      (mode & ~umask)
 26     //  返回值:文件描述符(正整数)(系统调用接口的操作句柄)失败:-1
 27     int fd = open("./test.txt", O_RDWR | O_CREAT | O_APPEND | O_TRUNC, 0664);
 28     if (fd < 0) {
 29         perror("open error");
 30         return -1;
 31     }
 32     char *ptr = "jintianzhilaile 20 ren\n";
 33     //ssize_t write(int fd, const void *buf, size_t count);
 34     //  fd:     open返回的文件描述符
 35     //  buf:   要写入的数据
 36     //  count: 要写入的数据长度
 37     //  返回值:实际写入的数据长度(字节)  失败:-1
 38     int ret = write(fd, ptr, strlen(ptr));
 39     if (ret < 0) {
 40         perror("write error");
 41         return -1;
 42     }
 43 
 44     //off_t lseek(int fd, off_t offset, int whence);
 45     //  fd:     open返回的文件描述符
 46     //  offset: 偏移量
 47     //  whence:偏移起始位置
 48     //          SEEK_SET    文件起始位置
 49     //          SEEK_CUR    当前读写位置
 50     //          SEEK_END    文件末尾位置
 51     //  返回值:从文件起始位置到当前读写位置的偏移量 失败:-1
 52     lseek(fd, 0, SEEK_SET);
 53 
 54     char buf[1024] = {0};
 55     //ssize_t read(int fd, void *buf, size_t count);
 56     //  fd:     open返回的文件描述符
 57     //  buf:    内存首地址,用于存储读取的数据
 58     //  count: 要读取的数据长度
 59     //  返回值:实际读取的数据长度(字节) 失败:-1
 60     ret = read(fd, buf, 1023);
 61     if (ret < 0) {
 62         perror("read error");
 63         return -1;
 64     }
 65     printf("read buf:[%d-%s]\n", ret, buf);
 66 
 67     //int close(int fd);
 68     close(fd);
 69     return 0;
 70 }

文件流指针和文件描述符比较:

  • 库函数的操作句柄是文件流指针
  • 系统调用接口的句柄是文件描述符       

进程运行在用户态/内核态:

    用户态切换到内核态:发起系统调用  

重定向:

改变数据流向,将写入(newfd)指定文件的数据,改变写入到(oldfd)另一个文件当中

  1 #include <stdio.h>
  2 #include <unistd.h>
  3 #include <fcntl.h>
  4 
  5 int main()
  6 {
  7     //close(1);
  8 
  9     int fd = open("./test.txt", O_RDWR | O_CREAT);
 10     if (fd < 0) {
 11         perror("open error");
 12         return -1;
 13     }
 14     //将要打印的数据,不写入标准输出,而是写入test.txt
 15     dup2(fd, 1);
 16     //\n刷新缓冲区,仅仅针对标准输出文件才有效
 17     //其它文件,\n仅仅具备换行效果
 18     printf("fd:%d\n", fd);//stdout  ->   1 ---> test.txt
 19     //fflush(stdout);
 20 
 21     //close是系统调用接口,关闭文件时不会刷新缓冲区(因为我们所说的这个     缓冲区是stdout的缓
    冲区(用户态的缓冲区))
 22     close(fd);
 23     return 0;
 24 }

文件系统

在linux下为了更好的对文件管理,所以要对文件进行分区。每一个文件系统分区当中会将磁盘划分为数据块。

文件存储过程:通过inode_bitmap在inode区域获取空闲inode节点,通过data_bitmap获取空闲数据块,在inode节点中记录文件信息以及数据块位置,并且将文件数据写入到数据块中,将自己的目录项添加到所在目录项当中。

目录文件:文件中记录着目录下的文件信息(文件名+inode节点)-----目录项

文件读取过程:在目录项当中通过文件名获取inode节点(文件唯一),通过inode节点号在inode节点区域找到inode节点,通过inode节点中数据块地址信息,在指定数据块中读取数据。

查看文件大小:sudo dump2fs -h /dev/sda1 | grep " lnode size"

软连接/硬链接

          软链接文件:  ln  -s  srcfile   destfile          (就像文件的快捷方式,是一个独立的文件)

          硬链接文件:  ln  srcfile  destfile                 (一个文件的名字(目录项),与源文件公用一个inode节点)

          区别:

                 1.删除源文件,软链接文件将失效,硬链接无影响(链接数 -1)

                 2.软链接可以跨分区创建,硬链接不可以

                 3.软链接可以对目录创建,硬链接不可以

动态库/静态库: 生成----------------------------------二进制指令的集合

           设置LIBRARY_PATH,以便gcc能够找到编译时需要的动态链接库。

           设置LD_LIBRARY_PATH,以便程序加载运行时能够自动找到需要的动态链接库。

           gcc编译过程: 预处理 ,编译, 汇编 ,链接

                          -fPIC  产生位置无关代码        -l (指定要链接的库名称)

                          --share  指定gcc生成动态库而不是可执行程序

          动态库的生成:命名:lib(前缀)    .so(后缀)   中间是库名称

                          gcc  -fPIC -c  child.c  -o child .o

                          gcc  --share  child.o  -o  libmychild.so

          静态库的生成:命名:lib(前缀)     .a(后缀)    中间是库名称

                          gcc  -c child.c -o child .o

                          ar    -cr  libmychild.a  child.o                        -c(创建)  -r(模块替换)

动态库的使用

解决办法:

  1. 将我们生成的动态库添加到系统默认搜索库的文件中系统中    (/lib64)或者(/usr/lib/)这两个都可以。

    2.设置设置动态库运行加载的环境变量    export LD_LIBRARY_PATH=.

静态库的使用

 

注意事项:

想要使用第三方静态库,不能使用-static 选项,因为static是生成静态链接可执行程序,所有的库都是用静态库,因为标准库时动态库所以在链接时会出错,因此只需要将第三方静态库拷贝到是定路径下,使用 -L选项指定链接搜索路径,那么这个时候链接的就是静态库;

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值