day26-系统IO(2022.2.23)

简介: day26-系统IO(2022.2.23)

Linux中,一切皆文件!



1.文件IO



浏览书本:《4.2.1系统IO》和《4.2.2标准IO》


问题:


  1. 两种IO操作方式有何相同点?不同点?关系?



相同点:两种方式都是用于操作文件。


不同点:


系统IO:在操作系统层面,由系统提供。


标准IO:在库函数层面,由标准C库提供。


(关系:标准IO函数,其本质也是调用系统IO)


  1. 他们的优缺点是什么?


系统IO:由系统提供,有最基本的操作函数。(简洁、精炼)(类似于菜市场)


好处:简洁单一,稳定,不需要消耗过多系统资源。


缺点:对于功能性要求较高的程序,更加繁琐。


标准IO:由标准C库提供,拥有多样化的操作函数。(功能多样)(类似于饭馆)


好处:复杂操作更为方便,函数接口更加多样化。


缺点:消耗系统资源更多,不适用于简单功能。


2.系统IO



——》在操作系统层面,由系统提供。


常用的接口函数:


  1. 文件的打开 open();


  1. 文件的关闭 close();


  1. 文件的写入 write();


  1. 文件的读取 read();


  1. 文件的偏移 lseek();


备注:


  1. 查看函数的用法:


直接查看man手册


查阅相关函数资料(书籍、网络)


  1. open打开文件描述符范围:3 ~ 1023


  1. 文件描述符 0~2分别对应不同的设备,自行open只能分配3以上。



  1. 当不再使用某个文件时,记得close关闭文件,释放资源。


(当程序结束时,所有资源也都会被释放)


  1. 文件偏移量:


也称为读写偏移量,读写操作都会先后移动。


每次重新打开一个文件,文件偏移量默认为0(位于文件开头)


3.主函数传参功能


主函数形式:


  1. 无参形式:


int main()
int main(void) //等同于上一个


  1. 带参形式:


 int main(int argc, const char *argv[])
 int main(int argc, const char **argv)


4.系统IO常用函数


  1. 控制硬件设备(绕过应用层,直接与驱动层通信)


       #include <sys/ioctl.h>
       int ioctl(int fd, unsigned long request, ...);


备注:


  1. 函数的形参个数最少2个,最多不限,由驱动程序决定。


比如6818开发板的蜂鸣器驱动有3个参数:


int ioctl(蜂鸣器硬件文件描述符, 电平状态, 引脚号);


蜂鸣器设备:”/dev/beep”



电平状态: 低电平0,高电平1(分别控制蜂鸣器响/不响)


引脚号: 固定为1号引脚



  1. 复制文件描述符:


dup和dup2


备注:


dup函数由系统自动分配最小且未用的文件描述符


dup2函数分配指定的文件描述符,如指定文件描述符已使用,会被替代。


  1. 文件控制:(软件、硬件。。)


fcntl()


备注:


可实现类似于dup和dup2的功能。


打开文件后,仍然能够设置/获取文件描述符的属性,无需重新打开文件。


  1. 内存映射 (作用:将文件与内存进行关联,提高操作效率!)


mmap()


空洞文件有什么用呢?空洞文件对多线程共同操作文件是及其有用的,有时候我们创建一个很大的文件,如果单个线程从头开始依次构建该文件需要很长的时间,有一种思路就是将文件分为多段,然后使用多线程来操作,每个线程负责其中一段数据的写入;这个有点像我们现实生活当中施工队修路的感觉,比如说修建一条高速公路,单个施工队修筑会很慢,这个时候可以安排多个施工队,每一个施工队负责修建其中一段,最后将他们连接起来。


来看一下实际中空洞文件的两个应用场景:


在使用迅雷下载文件时,还未下载完成,就发现该文件已经占据了全部文件大小的空间,这也是空洞文件;下载时如果没有空洞文件,多线程下载时文件就只能从一个地方写入,这就不能发挥多线程的作用了;如果有了空洞文件,可以从不同的地址同时写入,就达到了多线程的优势;


在创建虚拟机时,你给虚拟机分配了 100G 的磁盘空间,但其实系统安装完成之后,开始也不过只用了 3、4G 的磁盘空间,如果一开始就把 100G 分配出去,资源是很大的浪费。


1.open.c


#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
  // 文件路径:
    //相对路径:1.txt
    //绝对路径:/mnt/hgfs/GZ2203/04 文件IO/01 系统IO/code/1.txt
  int fd; // 文件描述符(操作句柄,文件编号)
  fd = open("1.txt", O_RDWR);
  if(fd == -1)
  {
    perror("open failed");  // 打印错误信息
    return -1;
  }
  printf("open success![%d]\n", fd);
  return 0;
}


2.open_close.c


#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
  // 文件路径:
    //相对路径:1.txt
    //绝对路径:/mnt/hgfs/GZ2203/04 文件IO/01 系统IO/code/1.txt
  int fd; // 文件描述符(操作句柄,文件编号)
  int cnt=1;
  while(1)
  {
    // 打开
    fd = open("1.txt", O_RDWR);
    if(fd == -1)
    {
      perror("open failed");  // 打印错误信息
      return -1;
    }
    printf("open success![%d][%d]\n", fd, cnt++);
    // 关闭
    // close(fd);
  }
  return 0;
}


3.creat.c


#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
  // 文件路径:
    //相对路径:1.txt
    //绝对路径:/mnt/hgfs/GZ2203/04 文件IO/01 系统IO/code/1.txt
  int fd; // 文件描述符(操作句柄,文件编号)
  // 打开
  fd = open("a.txt", O_RDWR|O_CREAT|O_EXCL, 0644);
  if(fd == -1)
  {
    perror("open failed");  // 打印错误信息
    return -1;
  }
  printf("open success![%d]\n", fd);
  // 关闭
  close(fd);
  return 0;
}


4.write.c


#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main()
{
  // 文件路径:
    //相对路径:1.txt
    //绝对路径:/mnt/hgfs/GZ2203/04 文件IO/01 系统IO/code/1.txt
  int fd; // 文件描述符(操作句柄,文件编号)
  // 1.打开(不存在则创建,存在则直接打开)
  fd = open("1.txt", O_RDWR|O_CREAT, 0644);
  if(fd == -1)
  {
    perror("open failed");  // 打印错误信息
    return -1;
  }
  printf("open success![%d]\n", fd);
  // 2.写入
    // sizeof(str1) :计算的是指针的大小(64位都是8字节)
  char *str1 = "a";
  int n_write = write(fd, str1, strlen(str1));
  printf("%d write\n", n_write);
  // 关闭
  close(fd);
  return 0;
}


5.read.c


#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main()
{
  // 文件路径:
    //相对路径:1.txt
    //绝对路径:/mnt/hgfs/GZ2203/04 文件IO/01 系统IO/code/1.txt
  int fd; // 文件描述符(操作句柄,文件编号)
  // 1.打开
  fd = open("1.txt", O_RDONLY, 0644);
  if(fd == -1)
  {
    perror("open failed");  // 打印错误信息
    return -1;
  }
  printf("open success![%d]\n", fd);
  // 2.读取
  char r_buf[10];
  bzero(r_buf, sizeof(r_buf));
  int n_read = read(fd, r_buf, sizeof(r_buf));
  printf("[%d]: %s\n", n_read, r_buf);
  // 3.关闭
  close(fd);
  return 0;
}


6.lseek偏移


#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main()
{
  // 文件路径:
    //相对路径:1.txt
    //绝对路径:/mnt/hgfs/GZ2203/04 文件IO/01 系统IO/code/1.txt
  int fd; // 文件描述符(操作句柄,文件编号)
  // 1.打开
  fd = open("1.txt", O_RDWR);
  if(fd == -1)
  {
    perror("open failed");  // 打印错误信息
    return -1;
  }
  printf("open success![%d]\n", fd);
  // 2.写入
  char w_buf[100] = "Lisi";
  int n_write = write(fd, w_buf, strlen(w_buf));
  printf("%d write\n", n_write);
  // 3.文件偏移量修改
  // lseek(fd, -4, SEEK_CUR); // 从当前位置向前偏移4个字节
  lseek(fd, 0, SEEK_SET);   // 从文件开头,不偏移
  // 4.读取
  char r_buf[10];
  bzero(r_buf, sizeof(r_buf));
  int n_read = read(fd, r_buf, sizeof(r_buf));
  printf("read[%d]: %s\n", n_read, r_buf);
  // 5.关闭
  close(fd);
  return 0;
}


7.读写偏移.c


#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main()
{
  // 1.打开文件
  int fd;
  fd = open("1.txt", O_RDWR);
  if(fd == -1)
  {
    perror("open failed");
    return -1;
  }
  // 2.输入名字并写入指定位置
  char name[10] = {0};
  printf("Pls Input: ");
  scanf("%s", name); while(getchar()!='\n');
    // 偏移到指定位置并写入
  lseek(fd, 6, SEEK_SET);
  write(fd, name, strlen(name));
  // 3.读取文件内容
    // 偏移到开头并读取
  lseek(fd, 0, SEEK_SET);
  char r_buf[100];
  bzero(r_buf, sizeof(r_buf));
  int n_read = read(fd, r_buf, sizeof(r_buf));
  printf("read(%d): %s\n", n_read, r_buf);
  // 4.关闭文件
  close(fd);
  return 0;
}


8.主函数传参.c


#include <stdio.h>
// 主函数
  // arg:argument形参简称 
  // c:count计数
  // v:varible变量
// int main(int argc, const char *argv[])
int main(int argc, const char **argv)
{
  int i;
  for(i=0; i<argc; i++)
    printf("argv[%d]: %s\n", i, argv[i]);
  return 0;
}


9.ioctl控制蜂鸣器.c


#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
int main()
{
  // 1.打开蜂鸣器
  int beep_fd = open("/dev/beep", O_RDWR);
  if(beep_fd == -1)
  {
    perror("open beep failed");
    return -1;
  }
  // 2.控制蜂鸣器
  int i;
  for(i=0; i<3; i++)
  {
    ioctl(beep_fd, 0, 1); //响
    sleep(1);
    ioctl(beep_fd, 1, 1); //不响
    sleep(1);
  }
  // 3.关闭蜂鸣器
  close(beep_fd);
  return 0;
}


10.dip和dup2复制文件描述符.c


#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
int main()
{
  int fd = open("1.txt", O_RDWR);
  if(fd == -1)
  {
    perror("open failed");
    return -1;
  }
  // 复制文件描述符,由系统分配新的文件描述符(最小、未用)
  int new_fd1 = dup(fd);
  char ch;
  lseek(fd, 0, SEEK_SET);
  read(fd, &ch, 1);
  printf("fd(%d): %c\n", fd, ch);
  lseek(new_fd1, 0, SEEK_SET);
  read(new_fd1, &ch, 1);
  printf("new_fd1(%d): %c\n", new_fd1, ch);
  // 复制文件描述符,自行指定新的文件描述符
  int new_fd2 = dup2(fd, 100);
  lseek(new_fd2, 0, SEEK_SET);
  read(new_fd2, &ch, 1);
  printf("new_fd2(%d): %c\n", new_fd2, ch);
  return 0;
}
相关文章
|
4月前
crash —— 获取系统的磁盘IO统计数据
crash —— 获取系统的磁盘IO统计数据
|
6月前
|
Linux 数据处理 C语言
【Linux】基础IO----系统文件IO & 文件描述符fd & 重定向(下)
【Linux】基础IO----系统文件IO & 文件描述符fd & 重定向(下)
85 0
|
6月前
|
缓存 网络协议 算法
【Linux系统编程】深入剖析:四大IO模型机制与应用(阻塞、非阻塞、多路复用、信号驱动IO 全解读)
在Linux环境下,主要存在四种IO模型,它们分别是阻塞IO(Blocking IO)、非阻塞IO(Non-blocking IO)、IO多路复用(I/O Multiplexing)和异步IO(Asynchronous IO)。下面我将逐一介绍这些模型的定义:
287 2
|
6月前
|
Linux C语言 C++
【Linux】基础IO----系统文件IO & 文件描述符fd & 重定向(上)
【Linux】基础IO----系统文件IO & 文件描述符fd & 重定向(上)
63 0
|
7月前
使用字节输入流报错 java.io.FileNotFoundException: srcdruid.properties (系统找不到指定的文件。)
使用字节输入流报错 java.io.FileNotFoundException: srcdruid.properties (系统找不到指定的文件。)
51 0
|
8月前
|
移动开发 前端开发 JavaScript
uniapp中IO模块(管理本地文件系统)的常用功能封装
uniapp中IO模块(管理本地文件系统)的常用功能封装
743 1
|
8月前
|
安全 Linux vr&ar
【Linux 系统】基础 IO(动静态库)-- 详解
【Linux 系统】基础 IO(动静态库)-- 详解
|
8月前
|
存储 固态存储 Linux
【Linux 系统】基础 IO(文件系统 & inode & 软硬链接)-- 详解
【Linux 系统】基础 IO(文件系统 & inode & 软硬链接)-- 详解
|
8月前
|
存储 Java 数据库
学籍管理系统【IO流+GUI】(Java课设)
学籍管理系统【IO流+GUI】(Java课设)
40 0
|
8月前
|
存储 Java 数据库
酒店用户管理系统【IO流+GUI】(Java课设)
酒店用户管理系统【IO流+GUI】(Java课设)
29 0