美文网首页
dispatch io.h

dispatch io.h

作者: 想聽丿伱說衹愛我 | 来源:发表于2020-07-22 17:20 被阅读0次

    版本:iOS13.5

    io.h

    dispatch其他文件通道

    索引

    • dispatch_read
      通过文件描述符异步读取数据
    • dispatch_write
      通过文件描述符异步写入数据
    • dispatch_io_create
      根据文件描述符创建调度I / O通道
    • dispatch_io_create_with_path
      根据路径名创建调度I / O通道
    • dispatch_io_create_with_io
      从现有的调度I / O通道创建一个新的调度I / O通道
    • dispatch_io_read
      在指定的I / O通道上异步执行读取操作
    • dispatch_io_write
      在指定的I / O通道上异步执行写入操作
    • dispatch_io_close
      关闭指定的I / O通道以进行新的读取或写入操作
    • dispatch_io_barrier
      在指定的I / O通道上安排屏障操作
    • dispatch_io_get_descriptor
      获取I / O通道的文件描述符
    • dispatch_io_set_high_water
      设置I / O通道上所有操作的高水位线
    • dispatch_io_set_low_water
      设置I / O通道上所有操作的低水位线
    • dispatch_io_set_interval
      设置一个纳秒间隔,所有操作的回调将按间隔时间排队。

    详解

    • 通过文件描述符异步读取数据
    void dispatch_read(dispatch_fd_t fd, size_t length, 
        dispatch_queue_t queue, void (^handler)(dispatch_data_t data, int error));
    

    当异步读取操作完成或发生错误时,将handler加入队列queue再执行。
    fd 要读取数据的文件描述符 可通过下面代码创建

    //文件位置
    NSString *path = [[NSBundle mainBundle] pathForResource:@"222" ofType:@"jpeg"];
    dispatch_fd_t fd = open(path.UTF8String, O_RDWR);
    #define O_RDONLY        0x0000         //只读
    #define O_WRONLY        0x0001         //只写
    #define O_RDWR          0x0002         //读写
    #define O_ACCMODE       0x0003         //
    

    length 从文件描述符读取的数据长度 若为SIZE_MAX,表示读取文件描述符当前可用的所有数据。
    queue 队列 通过dispatch_queue_create创建
    handler 读取完成时回调
    data 从文件描述符读取的数据
    error 读取操作的错误;如果读取成功,则为0。

    例:
        //文件位置
        NSString *path = [[NSBundle mainBundle] pathForResource:@"222" ofType:@"jpeg"];
        //创建fd
        dispatch_fd_t fd = open(path.UTF8String, O_RDWR);
        //创建队列
        dispatch_queue_t queue = dispatch_queue_create("io_queue", DISPATCH_QUEUE_CONCURRENT);
        dispatch_read(fd, SIZE_MAX, queue, ^(dispatch_data_t  _Nonnull data, int error) {
            UIImage *image = [UIImage imageWithData:(NSData *)data];
            NSLog(@"%f %f", image.size.width, image.size.height);
            close(fd);
        });
    
    • 通过文件描述符异步写入数据
    void dispatch_write(dispatch_fd_t fd, dispatch_data_t data,
        dispatch_queue_t queue, void (^handler)(dispatch_data_t _Nullable data, int error));
    

    当异步写入操作完成或发生错误时,将handler加入队列queue再执行。
    data 要写入文件描述符的数据对象
    handler 写入操作完成时回调
    data 无法写入I / O通道的数据,写入成功时为NULL。
    error 写入操作的错误;如果写入成功,则为0。

    例:
        dispatch_queue_t queue = dispatch_queue_create("io_queue", DISPATCH_QUEUE_CONCURRENT);
        NSString *path1 = [[NSBundle mainBundle] pathForResource:@"333" ofType:@"jpeg"];
        dispatch_fd_t fd1 = open(path1.UTF8String, O_RDWR);
        char charbuffer[] = {"1234567890"};
        dispatch_data_t data = dispatch_data_create(charbuffer, 10 * sizeof(char), queue, NULL);
        dispatch_write(fd1, data, queue, ^(dispatch_data_t  _Nullable data, int error) {
            NSLog(@"%d", error);
            close(fd1);
        });
    
    • 根据文件描述符创建调度I / O通道
    dispatch_io_t dispatch_io_create(dispatch_io_type_t type, dispatch_fd_t fd,
                          dispatch_queue_t queue, void (^cleanup_handler)(int error));
    

    type io通道类型

    //此类型通道的读取和写入操作是按顺序执行的(按创建顺序)
    //并且在操作开始执行时在文件指针位置处读取/写入数据。
    //可以同时执行不同类型的操作(读与写)。
    //传递给此类型通道上的操作的偏移量off_t offset将无效
    #define DISPATCH_IO_STREAM 0
    //可以同时执行这种类型的通道上的读取和写入操作,并以指定的偏移量off_t offset读取/写入数据。
    //为无法查找的文件描述符创建此类型的通道将导致错误。
    #define DISPATCH_IO_RANDOM 1
    

    cleanup_handler 当系统放弃对文件描述符的控制权时要放入队列queue中的回调
    error 如果由于创建通道失败使系统放弃控制,则为错误,否则为0

    例:
        NSString *path = [[NSBundle mainBundle] pathForResource:@"222" ofType:@"jpeg"];
        dispatch_fd_t fd = open(path.UTF8String, O_RDWR);
        dispatch_queue_t queue = dispatch_queue_create("io_queue", DISPATCH_QUEUE_CONCURRENT);
        dispatch_io_t io = dispatch_io_create(DISPATCH_IO_RANDOM, fd, queue, ^(int error) {
            close(fd);
        });
    
    • 根据路径名创建调度I / O通道
    dispatch_io_t dispatch_io_create_with_path(dispatch_io_type_t type, 
          const char *path, int oflag, mode_t mode,
          dispatch_queue_t queue, void (^cleanup_handler)(int error));
    

    当通道上的第一个I / O操作准备好执行时,指定的路径,oflag和mode参数将传递给open(2)
    path 绝对路径
    oflag 在路径中打开文件时传递给open(2)的标志
    mode 在路径创建文件时传递给open(2)的模式,否则为0。
    cleanup_handler 系统关闭路径下的文件时放入队列queue的回调
    error 如果创建或打开指定文件的通道失败使系统放弃控制时,则为错误,否则为0

    例:
        NSString *path = [[NSBundle mainBundle] pathForResource:@"222" ofType:@"jpeg"];
        dispatch_queue_t queue = dispatch_queue_create("io_queue", DISPATCH_QUEUE_CONCURRENT);
        dispatch_io_t io1 = dispatch_io_create_with_path(DISPATCH_IO_RANDOM, path.UTF8String, 0, 0, queue, ^(int error) {
            close(fd);
        });
    
    • 从现有的调度I / O通道创建一个新的调度I / O通道
    dispatch_io_t dispatch_io_create_with_io(dispatch_io_type_t type, dispatch_io_t io,
        dispatch_queue_t queue, void (^cleanup_handler)(int error));
    

    新通道继承与现有通道关联的文件描述符或路径名,但不继承其通道类型type或策略
    策略为(dispatch_io_set_high_waterdispatch_io_set_low_waterdispatch_io_set_interval)等
    io 原io通道
    cleanup_handler 当系统放弃对文件描述符的控制(或重新关闭路径中的文件)时放入队列queue的回调
    error 如果由于创建通道失败使系统放弃控制,则为错误,否则为0

    例:
        NSString *path = [[NSBundle mainBundle] pathForResource:@"222" ofType:@"jpeg"];
        dispatch_fd_t fd = open(path.UTF8String, O_RDWR);
        dispatch_queue_t queue = dispatch_queue_create("io_queue", DISPATCH_QUEUE_CONCURRENT);
        dispatch_io_t io = dispatch_io_create(DISPATCH_IO_RANDOM, fd, queue, ^(int error) {
            close(fd);
        });
        dispatch_io_t io2 = dispatch_io_create_with_io(DISPATCH_IO_RANDOM, io, queue, ^(int error) {
            
        });
    
    • 在指定的I / O通道上异步执行读取操作
    void dispatch_io_read(dispatch_io_t channel, off_t offset,size_t length,
        dispatch_queue_t queue,dispatch_io_handler_t io_handler);
    

    根据系统的一般负载和在I / O通道上指定的策略,将io_handler回调在queue上排队一次或多次。
    channel I / O通道
    offset 相对于从其开始读取的通道位置的偏移量(仅适用于DISPATCH_IO_RANDOM)。
    length 从I / O通道读取的数据长度,若为SIZE_MAX,表示全部读取
    io_handler 准备好传递数据时的回调

    typedef void (^dispatch_io_handler_t)(bool done, dispatch_data_t _Nullable data,
            int error);
    

    done 指示操作是否完成
    data 从I / O通道读取的数据的对象,或者为NULL
    error 读取操作的错误;如果读取成功,则为0

    例:
        NSString *path = [[NSBundle mainBundle] pathForResource:@"222" ofType:@"jpeg"];
        dispatch_fd_t fd = open(path.UTF8String, O_RDWR);
        dispatch_queue_t queue = dispatch_queue_create("io_queue", DISPATCH_QUEUE_CONCURRENT);
        dispatch_io_t io = dispatch_io_create(DISPATCH_IO_RANDOM, fd, queue, ^(int error) {
            close(fd);
        });
        dispatch_io_read(io, 0, SIZE_MAX, queue, ^(bool done, dispatch_data_t  _Nullable data, int error) {
            if (error == 0) {
                size_t len = dispatch_data_get_size(data);
                if (len > 0) {
                    UIImage *image = [UIImage imageWithData:(NSData *)data];
                    NSLog(@"%f %f", image.size.width, image.size.height);
                }
            }
            if (done) {
                NSLog(@"已全部读取完成");
            }
        });
    输出:
    658.000000 298.000000
    已全部读取完成
    
    • 在指定的I / O通道上异步执行写入操作
    void dispatch_io_write(dispatch_io_t channel, off_t offset, dispatch_data_t data,
        dispatch_queue_t queue, dispatch_io_handler_t io_handler);
    

    根据系统的一般负载和在I / O通道上指定的策略,将io_handler回调在queue上排队一次或多次。
    offset 相对于开始写入的通道位置偏移(仅适用于DISPATCH_IO_RANDOM
    data 要写入I / O通道的数据。数据对象将由系统保留,直到写入操作完成
    io_handler 传递数据时的回调

    typedef void (^dispatch_io_handler_t)(bool done, dispatch_data_t _Nullable data,
            int error);
    

    done 指示操作是否完成
    data 被写入I / O通道的剩余的数据对象,若全部写入则为NULL
    error 写入操作的错误;如果写入成功,则为0

    例:
        NSString *path = [[NSBundle mainBundle] pathForResource:@"222" ofType:@"jpeg"];
        dispatch_fd_t fd = open(path.UTF8String, O_RDWR);
        dispatch_queue_t queue = dispatch_queue_create("io_queue", DISPATCH_QUEUE_CONCURRENT);
        dispatch_io_t io = dispatch_io_create(DISPATCH_IO_RANDOM, fd, queue, ^(int error) {
            close(fd);
        });
        char charbuffer[] = {"1234567890"};
        dispatch_data_t data = dispatch_data_create(charbuffer, 10 * sizeof(char), queue, NULL);
        dispatch_io_write(io, 0, data, queue, ^(bool done, dispatch_data_t  _Nullable data, int error) {
            if (done) {
                NSLog(@"已全部写入完成");
            }
        });
    输出:
    已全部写入完成
    
    • 关闭指定的I / O通道以进行新的读取或写入操作
    void dispatch_io_close(dispatch_io_t channel, dispatch_io_close_flags_t flags);
    

    flags 关闭操作的标志
    #define DISPATCH_IO_STOP 0x1当通道关闭时,停止对通道的未完成操作

    • 在指定的I / O通道上安排屏障操作
    void dispatch_io_barrier(dispatch_io_t channel, dispatch_block_t barrier);
    

    barrier回调会放入通道channel的队列queue中,通道上的所有先前的调度操作都会完成。但直到barrier回调执行之前,之后添加的调度操作都不会开始。
    barrier 屏障操作回调typedef void (^dispatch_block_t)(void);

    例:
        NSString *path = [[NSBundle mainBundle] pathForResource:@"222" ofType:@"jpeg"];
        dispatch_fd_t fd = open(path.UTF8String, O_RDWR);
        dispatch_queue_t queue = dispatch_queue_create("io_queue", DISPATCH_QUEUE_CONCURRENT);
        dispatch_io_t io = dispatch_io_create(DISPATCH_IO_RANDOM, fd, queue, ^(int error) {
            close(fd);
        });
        dispatch_io_read(io, 0, SIZE_MAX, queue, ^(bool done, dispatch_data_t  _Nullable data, int error) {
            if (done) {
                NSLog(@"读取操作1完成");
            }
        });
        dispatch_io_barrier(io, ^{
            sleep(10);
        });
        dispatch_io_read(io, 0, SIZE_MAX, queue, ^(bool done, dispatch_data_t  _Nullable data, int error) {
            if (done) {
                NSLog(@"读取操作2完成");
            }
        });
    输出:操作1完成10秒后操作2才完成
    16:20:19.506332+0800 DEMO[67133:7469651] 读取操作1完成
    16:20:29.510332+0800 DEMO[67133:7469652] 读取操作2完成
    
    • 获取I / O通道的文件描述符
    dispatch_fd_t dispatch_io_get_descriptor(dispatch_io_t channel);
    
    • 设置I / O通道上所有操作的高水位线
    void dispatch_io_set_high_water(dispatch_io_t channel, size_t high_water);
    

    high_water 高水位线的字节数,默认为SIZE_MAX

    • 设置I / O通道上所有操作的低水位线
    void dispatch_io_set_low_water(dispatch_io_t channel, size_t low_water);
    

    I / O管道通常接收大于低水位线的数据量。如果需要固定大小的数据量,则将低水位标记和高水位标记都设置为该大小。
    low_water 低水位线的字节数,默认未指定,若要让操作不执行回调,请将此值设为SIZE_MAX

    例:
        dispatch_io_set_high_water(io, 10000);
        dispatch_io_read(io, 0, SIZE_MAX, queue, ^(bool done, dispatch_data_t  _Nullable data, int error) {
            NSLog(@"error=%d data_size =%ld", error, dispatch_data_get_size(data));
        });
    输出:总共读取了5次 每次读取最大为10000
    error=0 data_size =10000
    error=0 data_size =10000
    error=0 data_size =10000
    error=0 data_size =2909
    error=0 data_size =0
    例:
        dispatch_io_set_high_water(io, 9000);
        dispatch_io_set_low_water(io, 8000);
        dispatch_io_read(io, 0, SIZE_MAX, queue, ^(bool done, dispatch_data_t  _Nullable data, int error) {
            NSLog(@"error=%d data_size =%ld", error, dispatch_data_get_size(data));
        });
    输出:ps:```dispatch_io_set_low_water```用法不明,有待开发
    error=0 data_size =9000
    error=0 data_size =9000
    error=0 data_size =9000
    error=0 data_size =5909
    error=0 data_size =0
    
    
    • 设置一个纳秒间隔,所有操作的回调将按间隔时间排队。
    void dispatch_io_set_interval(dispatch_io_t channel,
        uint64_t interval, dispatch_io_interval_flags_t flags);
    

    这允许应用程序接收有关读取和写入操作进度的定期反馈,例如为了显示进度条。
    interval 各回调之间的间隔时间(纳秒)
    flags 数据传递行为的标志
    #define DISPATCH_IO_STRICT_INTERVAL 0x1即使准备好传递的数据量低于低水位线(或零),也可以按通道的间隔设置让回调排队。

    例:
        dispatch_io_set_interval(io, 1 * NSEC_PER_SEC, DISPATCH_IO_STRICT_INTERVAL);
        dispatch_io_read(io, 0, SIZE_MAX, queue, ^(bool done, dispatch_data_t  _Nullable data, int error) {
            if (done) {
                NSLog(@"读取操作1完成");
            }
        });
        dispatch_io_read(io, 0, SIZE_MAX, queue, ^(bool done, dispatch_data_t  _Nullable data, int error) {
            if (done) {
                NSLog(@"读取操作2完成");
            }
        });
        dispatch_io_read(io, 0, SIZE_MAX, queue, ^(bool done, dispatch_data_t  _Nullable data, int error) {
            if (done) {
                NSLog(@"读取操作3完成");
            }
        });
    输出:并没有间隔一秒 不知为何
    16:58:43.854467+0800 DEMO[67854:7526310] 读取操作1完成
    16:58:43.854501+0800 DEMO[67854:7526297] 读取操作2完成
    16:58:43.854521+0800 DEMO[67854:7526328] 读取操作3完成
    

    用法

    用法1:并行
        NSString *path = [[NSBundle mainBundle] pathForResource:@"222" ofType:@"jpeg"];
        dispatch_fd_t fd = open(path.UTF8String, O_RDWR);
        dispatch_queue_t queue = dispatch_queue_create("io_queue", DISPATCH_QUEUE_CONCURRENT);
        dispatch_io_t io = dispatch_io_create(DISPATCH_IO_RANDOM, fd, queue, ^(int error) {
            close(fd);
        });
        long long fileSize = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil].fileSize;
        NSMutableData *totalData = [[NSMutableData alloc] initWithLength:fileSize];
        dispatch_group_t group = dispatch_group_create();
        size_t offset = 1024;
        for (off_t currentSize = 0; currentSize <= fileSize; currentSize += offset) {
            dispatch_group_enter(group);
            dispatch_io_read(io, currentSize, offset, queue, ^(bool done, dispatch_data_t  _Nullable data, int error) {
                if (error == 0) {
                    size_t len = dispatch_data_get_size(data);
                    if (len > 0) {
                        const void *bytes = NULL;
                        (void)dispatch_data_create_map(data, &bytes, &len);
                        //当queue为DISPATCH_QUEUE_CONCURRENT并行时 通过replaceBytesInRange来替换数据
                        [totalData replaceBytesInRange:NSMakeRange(currentSize, len) withBytes:bytes];
                    }
                }
                if (done) {
                    dispatch_group_leave(group);
                }
            });
        }
        dispatch_group_notify(group, queue, ^{
            UIImage *image = [UIImage imageWithData:totalData];
            NSLog(@"%f %f", image.size.width, image.size.height);
        });
    用法2:串行
        NSString *path = [[NSBundle mainBundle] pathForResource:@"222" ofType:@"jpeg"];
        dispatch_fd_t fd = open(path.UTF8String, O_RDWR);
        dispatch_queue_t queue = dispatch_queue_create("io_queue", DISPATCH_QUEUE_SERIAL);
        dispatch_io_t io = dispatch_io_create(DISPATCH_IO_RANDOM, fd, queue, ^(int error) {
            close(fd);
        });
        long long fileSize = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil].fileSize;
        NSMutableData *totalData = [[NSMutableData alloc] init];
        dispatch_group_t group = dispatch_group_create();
        size_t offset = 1024;
        for (off_t currentSize = 0; currentSize <= fileSize; currentSize += offset) {
            dispatch_group_enter(group);
            dispatch_io_read(io, currentSize, offset, queue, ^(bool done, dispatch_data_t  _Nullable data, int error) {
                if (error == 0) {
                    size_t len = dispatch_data_get_size(data);
                    if (len > 0) {
                        //当queue为DISPATCH_QUEUE_SERIAL串行时 通过appendData直接合并数据
                        [totalData appendData:(NSData *)data];
                    }
                }
                if (done) {
                    dispatch_group_leave(group);
                }
            });
        }
        dispatch_group_notify(group, queue, ^{
            UIImage *image = [UIImage imageWithData:totalData];
            NSLog(@"%f %f", image.size.width, image.size.height);
        });
    用法3:io类型为DISPATCH_IO_STREAM
        NSString *path = [[NSBundle mainBundle] pathForResource:@"222" ofType:@"jpeg"];
        dispatch_fd_t fd = open(path.UTF8String, O_RDWR);
        dispatch_queue_t queue = dispatch_queue_create("io_queue", DISPATCH_QUEUE_SERIAL);
        dispatch_io_t io = dispatch_io_create(DISPATCH_IO_STREAM, fd, queue, ^(int error) {
            close(fd);
        });
        long long fileSize = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil].fileSize;
        NSMutableData *totalData = [[NSMutableData alloc] init];
        dispatch_group_t group = dispatch_group_create();
        size_t offset = 1024;
        for (off_t currentSize = 0; currentSize <= fileSize; currentSize += offset) {
            dispatch_group_enter(group);
            //io类型为DISPATCH_IO_STREAM时 不用设置off_t offset属性
            dispatch_io_read(io, 0, offset, queue, ^(bool done, dispatch_data_t  _Nullable data, int error) {
                if (error == 0) {
                    size_t len = dispatch_data_get_size(data);
                    if (len > 0) {
                        [totalData appendData:(NSData *)data];
                    }
                }
                if (done) {
                    dispatch_group_leave(group);
                }
            });
        }
        dispatch_group_notify(group, queue, ^{
            UIImage *image = [UIImage imageWithData:totalData];
            NSLog(@"%f %f", image.size.width, image.size.height);
        });
    

    相关文章

      网友评论

          本文标题:dispatch io.h

          本文链接:https://www.haomeiwen.com/subject/rjtykktx.html