• 系统编程(一)文件IO


    应用层: 只负责写代码,调用内核层


    内核层 : 接到应用层发来的通知,去操作硬件(驱动)


    物理层:根据内核层的需求去操作硬件

    一文件IO

            1:为什么学习IO:

                  嵌入式:软件控制硬件,嵌入式对内存进行操作,和内核进行操作来完成操作硬件。

     IO:学习API函数接口

    linux下一切皆文件

    linux是一个多任务的操作系统--------》多进程

    IO是在应用层和内核层之间交互。

    linux操作系统将文件分为2类:

                    文本文件:   --------------------》.sh,c,c++  按照程序员的逻辑

                    二进制文件: --------------------》a.out       按计算机的逻辑去存储

    2 IO是什么:

            input和output

            对内存的输入和输出

            内存往外存为输出,外村往内存为输入

    内存的特点:

                    本身速度快,数据掉电就丢失,特点贵

    外存:        

                    本身速度慢,数据永久保存,掉电不丢失,便宜

    3:如何使用IO

    对文件的操作: 打开文件-----------读写文件------------关闭文件

    IO分类: 

            文件IO:由操作系统提供的API接口,也被称为系统调用

                            每个操作系统的API接口都不一样,

                            也就造成linux下可执行文件移植到其他平台不能直接使用,因为接口不一致

            标准IO: stdio.h,也成为标准C库函数,ANSI C库提供的API接口,标准IO是在文件IO的基础上封装出来的

    1.5文件IO的接口

    open       read      write         close      lseek

    注意:此为linxu下的接口

    _open _write _close _read 

    此为windos操作接口

    Open Read Write Close

    ios函数接口

    1.6man手册

    man是在线函数查找手册

    man 3       库调用       程序库中的函数

    man 2       系统调用,内核提供的函数

    1.7:errno

    errno是一个全局变量,保存在#include 中,用于标注错误信息,

    当函数报错返回时,会将这个全局变量根据错误信息表中的对应的号码设置一下

    全局变量危险哦

    1.8:文件描述符:

    文件描述符:是一个文件标志,为数组的下标,是一个int类型的数据,值一般很小

                            动态分配,一般从3开始

    ./a.out   刚运行,内核会自动打开三个设备文件,返回三个文件描述符。

    标准输入  -------------0         stdin

    标准输出 --------------1        stdout

    标准错误输出 ---------------2   stderr

    1.9open

    头文件:

            #include       基本系统数据类型的头文件

            #include         是unix/linux系统定义文件状态所在的伪标准头文件

            #include                 fcntl.h定义了很多宏和open,fcntl函数原型

    原型:

            int open(const char *pathname,int flags);

            int open(const char *pathname,int flags,mode_t mode); 

            mode_t 实际上也就是一种无符号整数。

    功能:

            打开一个文件

    参数:

            pathname:路径及名称,字符串形式

            flag:打开文件的方式:

                                   必须包括:(三选一)

            O_RDONLY:只读权限打开文件  必须存在

            O_WRONLY:只写权限打开文件

            O_RDWR:读写权限打开文件

                                    附加参数(以或的形式去附加)

            O_APPEND:以追加写的方式打开文件

            O_CREAT:如果文件存在则打开文件,如果文件不存在,则创建文件,如果使用了  O_CREAT这个参数,则需要使用open的第三个参数给与权限, 给与权限是一个8进制的整形,以0开头 ,例如:O_CREAT,0664

            O_EXCL:如果文件存在则报错返回

            O_TRUNC:以清空的方式打开文件

            O_NONBLOCK:以非阻塞方式打开一个文件

    返回值:

            成功:返回一个文件描述符

            失败:返回-1

    注意:

    使用0666创建文件为什么出来的是0664呢? 是由于操作系统有一个叫做文件掩码的机制,将其它用户权限的可写权限抹掉

    使用 umask查看文件掩码

    jsetc@linux:~/jsetc/210/day14$ umask 0002

            文件掩码取反再相与得到

    修改文件掩码: umask + 想要修改的值 使用文件掩码取反后和文件权限相与得到最后的文件的权限                            

    ll查看权限    

                                            

    1. #include
    2. #include
    3. #include
    4. #include
    5. int main(int argc, char const *argv[])
    6. {
    7. int fd = open("1.txt",O_RDWR|O_EXCL);
    8. if(fd == -1)
    9. {
    10. perror("open");
    11. }
    12. perror("open");
    13. return 0;
    14. }

    2.0  read

    头文件:

                   #include  

    由字面意思,unistd.h是unix std的意思,是POSIX标准定义的unix类系统定义符号常量的头文件,

    包含了许多UNIX系统服务的函数原型,例如read函数、write函数和getpid函数。

    原型:

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

    功能:        

            对一个文件进行读取

    参数:

            fd:目标文件描述符 --------》对哪个文件进行读取

            buf:存放读取到的数据------》读取到的数据存放的地址

            count:读多少

    返回值

            成功返回读取到的字节数

            失败返回-1

            读到末尾返回0

    注意:但是最后一次read时如果文件剩余字节不够count,读到文件末尾时返回已经读到的字节个数 ,再一次读取时返回0

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. int main(int argc, char const *argv[])
    7. {
    8. int fd = open("1.txt",O_RDONLY);
    9. if(-1 == fd)
    10. {
    11. perror("open");
    12. return -1;
    13. }
    14. perror("open");
    15. char buf[1024] = {0};//要初始化哦,不然会有垃圾数据
    16. int ret;
    17. if(-1 == (ret = read(fd,buf,10)) )
    18. {
    19. perror("read");
    20. return -1;
    21. }
    22. perror("read");
    23. printf("%s\n",buf);
    24. printf("%d\n",ret);
    25. return 0;
    26. }

    2.1write

    头文件:

             #include

    原型:

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

            size_t 是 long int 类型

    功能:        

            对一个文件进行写入操作

    参数:

            fd:文件描述符           ---------》对哪个文件操作

            buf:要写入数据的地址--------》写入的具体数据

            count:写入数据的大小

    返回值:

            成功返回写入的字节个数

            失败返回-1

            

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. int main(int argc, char const *argv[])
    9. {
    10. int fd = open("1.txt",O_RDWR|O_APPEND);
    11. if(-1 == fd)
    12. {
    13. perror("open");
    14. printf("errno = %d\n",errno);
    15. return -1;
    16. }
    17. perror("open");
    18. char buf[] = "hello world\n";
    19. int ret;
    20. if(-1 == (ret = write(fd,buf,strlen(buf))))
    21. {
    22. perror("write");
    23. return -1;
    24. }
    25. perror("write");
    26. printf("%d\n",ret);
    27. if(-1 == write(fd,"zhangriyu?",9))
    28. {
    29. perror("write");
    30. return -1;
    31. }
    32. return 0;
    33. }

    2.2lseek

    头文件:

            #include

            #include

    原型:

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

            off_t类型用于指示文件的偏移量,常就是long类型

    功能:

            操作读写指针,对读写指针偏移

    参数:

            fd:文件描述符

            offset:如何偏移,偏移多少

            如果该数为负数,代表向左进行偏移,如果偏移出了文件的开头,会报错返回

            如果该数为正数,代表向右偏移,如果偏移出了文件的末尾,会扩大文件,用‘\0’来                填充,那么此类文件被称为---空洞文件--

            注意:如果偏移后没有对其进行任何写入操作,内核会认为该偏移无效,不会扩大文件           大小

            whence:基准位置 ---》根据哪一个位置进行偏移

            SEEK_SET:根据文件开头进行偏移

                    The file offset is set to offset bytes.

            SEEK_CUR:根据用户当前位置进行偏移

                    The file offset is set to its current location plus offset bytes.

            SEEK_END:根据文件末尾进行偏移

                    The file offset is set to the size of the file plus offset bytes.

    返回值:

            成功:返回偏移的字节个数(根据文件开头来定)

            失败:返回-1

            

    练习:先对一个文件进行写入helloworld,然后从这个文件将helloworld读出来,打印到终端上

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. int main(int argc, char const *argv[])
    8. {
    9. int fd = open(argv[1], O_RDWR|O_CREAT,0664);
    10. if(fd == -1)
    11. {
    12. perror("open");
    13. return -1;
    14. }
    15. perror("open");
    16. char buf[] = "hello world";
    17. if(-1 == write(fd, buf, strlen(buf)))
    18. {
    19. perror("read");
    20. return -1;
    21. }
    22. int ret;
    23. if(-1 == (ret = lseek(fd,0,SEEK_SET)))
    24. {
    25. perror("lseek");
    26. return -1;
    27. }
    28. perror("lseek");
    29. printf("%d\n",ret);
    30. char buf1[100] = {0};
    31. if(-1 == read(fd,buf1,11))
    32. {
    33. perror("read");
    34. return -1;
    35. }
    36. perror("read");
    37. printf("%s\n",buf1);
    38. return 0;
    39. }

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. int main(int argc, char const *argv[])
    7. {
    8. if(argc != 3)
    9. {
    10. printf("输入错误\n");
    11. return -1;
    12. }
    13. int fd = open(argv[1], O_RDONLY);
    14. if(-1 == fd)
    15. {
    16. perror("open");
    17. return -1;
    18. }
    19. perror("open");
    20. int fd1 = open(argv[2], O_WRONLY|O_CREAT,0664|O_TRUNC);
    21. if(-1 == fd1)
    22. {
    23. perror("open1");
    24. return -1;
    25. }
    26. perror("open1");
    27. char buf[1024] = {0};
    28. while(1)
    29. {
    30. ssize_t ret = read(fd,buf,1024);
    31. if(ret == -1)
    32. {
    33. perror("read");
    34. return -1;
    35. }
    36. if(0 == ret)
    37. {
    38. printf("读到文件末尾了,开始写入----\n");
    39. break;
    40. }
    41. if(-1 == write(fd1,buf,ret))
    42. {
    43. perror("write");
    44. return -1;
    45. }
    46. }
    47. close(fd);
    48. close(fd1);
    49. return 0;
    50. }

  • 相关阅读:
    ZMQ之多线程编程
    Warmup小记
    Centos 8查询当前时区
    组成目标货币的最少张数
    uniapp vuex正确的打开方式
    kafka可视化工具Kafka Tool安装使用
    警惕国外科技断供风险:CACTER邮件网关信创一体机为商业银行提供全国产化防护
    Windows设置SonarQube项目扫描
    StatefulSet
    创建型模式-抽象工厂模式(三)
  • 原文地址:https://blog.csdn.net/zrykk99/article/details/126240631