zoukankan      html  css  js  c++  java
  • 非阻塞io与记录锁

    非阻塞io

    1.对比
    阻塞io的例子:scanf从终端获取输入时,如果不输入程序就会一直停在那; 对一个已经有写锁的文件请求读时, 会一直空等直到前面的进程释放锁...
    非阻塞的例子:读取文件内容, 如果文件当前因加锁无法访问则立即出错返回

    2.非阻塞io设置方法
    a.调用open函数时, 指定O_NONBLOCK标志
    open(filename,O_RDWR,O_NONBLOCK)
    b.已经打开的fd, 调用fcntl将fd的O_NONBLOCK标志打开

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <fcntl.h>
    #include <string.h>
     
    char buf[500000];
     
    void set_fl(int fd,int flags){
        int val;
        if((val=fcntl(fd,F_GETFL,0))<0){
            perror("fcntl F_GETFL error");
            exit(1);
        } 
        val|=flags; 
        if(fcntl(fd,F_SETFL,val)<0){
            perror("fcntl F_SETFL error");
            exit(1);
        }
    }
    
    void clr_fl(int fd,int flags){
        int val;
        if((val=fcntl(fd,F_GETFL,0))<0){
            perror("fcntl F_GETFL error");
            exit(1);
        } 
        val &= ~flags; 
        if(fcntl(fd,F_SETFL,val)<0){
            perror("fcntl F_SETFL error");
            exit(1);
        }
    }
     
    int main(){
        int ntowrite,nwrite;
        char *ptr;
     
        ntowrite=read(STDIN_FILENO,buf,sizeof(buf));
        fprintf(stderr,"read %d bytes
    ",ntowrite);
     
        set_fl(STDOUT_FILENO,O_NONBLOCK);
     
        ptr=buf;
        while(ntowrite>0){
            errno=0;
            nwrite=write(STDOUT_FILENO,ptr,ntowrite);
            fprintf(stderr,"nwrite=%d,errno=%d
    ",nwrite,errno);
     
            if(nwrite>0){
                ptr += nwrite;
                ntowrite -= nwrite;
            }
        }
     
        clr_fl(STDOUT_FILENO,O_NONBLOCK);
        return 0;
    }
    

    执行 ./a.out < /etc/services 2>stderr.out
    查看stderr.out文件会发现write函数出现了很多次相同错误,
    在centos上, 出错的errno=11, Resource temporarily unavailable
    书本上测试的为errno=35, Resource deadlock avoided
    从结果上看, 在写入stdout时, 由于终端缓冲的原因没办法一次write完成, 所以分成很多次去写
    因为设置了O_NONBLOCK, 所以提交write任务后, 如果当前终端还在处理上一个循环的write, 则本次write立即返回并设置errno

    记录锁(文件锁).

    1.记录锁用于多进程对文件编辑的保护

    2.锁函数

    int fcntl(int fd, int cmd, struct flock *lock);
    
    cmd = F_GETLK,测试能否建立一把锁
    cmd = F_SETLK,设置锁
    cmd = F_SETLKW, 阻塞设置一把锁
    
    struct flock {
          short l_type;    /* 锁的类型: F_RDLCK, F_WRLCK, F_UNLCK */
          short l_whence;  /* 加锁的起始位置:SEEK_SET, SEEK_CUR, SEEK_END */
          off_t l_start;   /* 加锁的起始偏移,相对于l_whence */
          off_t l_len;     /* 上锁的字节数*/
          pid_t l_pid;     /* 已经占用锁的PID(只对F_GETLK 命令有效) */
          /*...*/
    };
    

    3.锁的继承和释放
    a.进程结束后, 进程所建立的锁全部释放
    b.fork产生的子进程不继承父进程的锁
    c.执行exec后, 新程序可以继承原执行程序的锁

    4.建议锁和强制锁
    建议锁:只关注fcntl加锁函数, open/read/write可以无视文件是否加锁
    强制锁:read/write/open函数执行时都要检查文件是否加锁

    值得注意的是, 强制锁的实现依赖系统

    下面的程序运行二个实例, 第二个实例会在lockfile那一步报错

    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <signal.h>
    #include <errno.h>
    #include <sys/stat.h>
    #include <fcntl.h>
     
    int lockfile(int fd){
        struct flock fl; 
        fl.l_type=F_WRLCK;
        fl.l_start=0;
        fl.l_whence=SEEK_SET;
        fl.l_len=0;
        return(fcntl(fd,F_SETLK,&fl));
    }
    #define FILE_MODE S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH
    int main(){
        int fd;
        char *filename="./test.txt";
        struct stat statbuf;
        if((fd=open(filename,O_RDWR|O_CREAT,FILE_MODE))<0){
            perror("open error");
            exit(1);
        }
        if(write(fd,"abcdef",6) != 6){
            perror("write error");
            exit(1);
        }
    /*
     *  if(fstat(fd,&statbuf)<0){
     *      perror("fstat error");
     *      exit(1);
     *  }
     *
     *  if(fchmod(fd,(statbuf.st_mode & ~S_IXGRP) | S_ISGID) <0){
     *      perror("fchmod error");
     *      exit(1);
     *  }
     */
        if(lockfile(fd)<0){
            perror("lockfile error");
            exit(1);
        }
        while(1){
            ;
        }
    }
    
  • 相关阅读:
    vue-awesome-swiper 子项目内容高度适配问题
    ajax的原理及应用
    display:none opacity:0以及visibility:hidden的区别
    javascript 创建型设计模式
    圣杯布局和双飞翼布局
    javascript->对象继承
    js 宏任务和微任务
    android->按钮底部定位上移
    ios移动端开发的坑
    jvm系列 (五) ---类加载机制
  • 原文地址:https://www.cnblogs.com/cfans1993/p/5657476.html
Copyright © 2011-2022 走看看