• Linux IO


    Linux 系统编程(IO)

    工具

    • strace: 根据系统调用
    • od -tcx: 查看二进制

    函数参数

    • 使用const修改的指针为传入参数
    • 不使用const的指针为传出参数

    string操作的函数

    • strtok: 分隔字符串

    IO

    • 函数
      • read
      • write
      • fcntl
      • iocntl
      • perror
      • strerror

    IO-1

    • 头文件 -> unistd.h, fcntl.h, stdio.h, errno.h

    • open(fd, mode, permission) 函数

      • mode为宏-> O_RDONLY, O_CREAT, O_APPEND, O_TRUNC(会将文件截断, 将文件的大小改成0), O_RDWR, O_BLOCK, O_NONBLOCK, 当有O_CREAT时有第三个参数权限, 要考虑到umask, open函数使用可变参数实现了函数重载
    • read(fd, buf, sizeof(buf))

    • write(fd, buf, ret) // ret是read函数返回的字节数, 0表示达到了文件末尾, -1是异常

    • close(fd)

    IO-2

    阻塞

    • 在读取终端设备或者网络设备的时候会出现阻塞, 也就是说在读取这些设备的时候可以这些设备并没有数据可读, 程序就会阻塞在这里

    • 默认情况下, open("/dev/tty", O_RDONLY)是阻塞的, 也就是说只有终端有输入才会往下执行程序

    • open函数进行非阻塞读取, 需要借助宏O_NONBLOCK设置位

      • 示例(这里忽略里错误处理)

        
        int fd = open("/dev/tty", O_RDONLY | O_NONBLOCK);
        int ret = 0;
        char buf[1024];
        char *msg = "try again...";
        
        while (ret = read(fd, buf, sizeof(buf))) {
            if (-1 == ret) {
                // 注意
                if (errno != EAGAIN) {
                    // STDOUT_FILENO 是数字1, STDIN_FILENO 是数字0
                    perror("error");
                    exit(1);
                }
                write(STDOUT_FILENO, msg, strlen(msg));
                sleep(1);
                continue;
            }
            write(STDOUT_FILENO, buf, ret);
        }
        
      • 在上例中, 如果终端没有数据, 则read函数返回-1, 但是这并不代表着read错误了, 如果没有数据, Linux会将errno这是为EAGAIN, 如果errno不是EAGAIN, 则读取错误

    • 在执行一个程序的时候, 默认会PCB指向的数组指针中会在0, 1, 2下标对应的位置创建file struct, 代表着stdin, stdout, stderr, 所以我们使用终端的时候, 终端已经被打开了, 在上面的程序中, 我们要向实现非阻塞的功能, 需要打开一个已经打开的文件, 这个是不必要的, Linux提供了fcntl函数用于修改已经打开的文件的属性

      • 示例
        
        // F_GETFL是Get File Flag, 获取文件属性, 文件属性就是一个int类型, 采用bitmap的方式实现保存多个属性
        int ret = 0;
        int flag = fcntl(STDOUT_FILENO, F_GETFL);
        // 将对应的位置1, 也许O_NONBLOCK是000000000000000000001000000
        // |即使加法, 在fnctl内部判断flag是否有O_NONBLOCK属性, 是通过flag & O_NONBLOCK, 如果返回的是1则表示有O_NONBLOCK属性, 0则表示没有
        flag |= O_NONBLOCK;
        char buf[1024];
        char *msg = "try again...";
        
        while (ret = read(STDOUT_FILENO, buf, sizeof(buf))) {
            if (-1 == ret) {
                // 注意
                if (errno != EAGAIN) {
                    // STDOUT_FILENO 是数字1, STDIN_FILENO 是数字0
                    perror("error");
                    exit(1);
                }
                write(STDOUT_FILENO, msg, strlen(msg));
                continue;
            }
            write(STDOUT_FILENO, buf, ret);
        }
        
    • 移动文件指针(lseek)

      • 三个表示状态的宏: SEEK_SET(文件起始位置), SEEK_CUR(当前位置), SEEK_END(末尾)
      • lseek(fd, offset, macro)返回当前指针到其实位置的偏移量, 可以用来估计文件大小
      • 示例
        
        int fd = open("./test.txt", O_RDONLY | O_CREAT, 0644);
        // 文件大小
        int offset = lseek(fd, 0, SEEK_END);
        // 追加数据
        write(...);
        close(fd);
        
    示例cp
    
    int main(int argc, char *argv[]) {
        char buf[1024] = {''};
        int ret = 0;
        if (argc < 3) {
            printf("Too Few Parameters
    ");
            return 1;
        }
        int fd_src = open(argv[1], O_RDONLY);
        int fd_dst = open(argv[2], O_RDWR | O_CREAT | O_TRUNC, 0666);
        while ((ret = read(fd_src, buf, sizeof(buf)))) {
            write(fd_dst, buf, ret);
        }
        close(fd_src);
        close(fd_dst);
        return 0;
    }
    
  • 相关阅读:
    Cookie 学习笔记
    IEDA的图片视频等文件在Tomcat上部署不能访问的问题
    JavaWeb 的路径访问问题,以及路径命名规则。
    HttpServlet 的 Request 方法 学习笔记
    Servlet概念 ,体系结构及配置 HTTP概念
    XML学习笔记
    IDEA创建Tomcat服务器,以及新创建的JaveWeb项目(JavaEE)如何部署在Tomcat上,以及出现404的原因,以及一些设置。
    IDEA将多个项目创建在同一个文件夹下,及创建JavaWeb项目方法
    Spring JDBCTemplate对象的增删查改写法 学习笔记
    Druid 数据库连接池技术(JDBCUtils工具类的编写) 学习笔记
  • 原文地址:https://www.cnblogs.com/megachen/p/10184395.html
Copyright © 2020-2023  润新知