LINUX 高级IO操作

LINUX 高级IO操作


一 知识点非常重要

二 非阻塞的IO
   系统调用: 低速系统调用,其他系统调用
   低速系统调用的类别:
   1)读网络设备,终端,管道等,暂时没有数据输入,则阻塞读操作
   2)同上的写操作,但不能接收时,也阻塞写操作
   3)等待某种条件的读写操作
   4)加锁的文件的读写操作
   5)某些ioctl操作
   6)进程通信间的函数
   通过文件描述符可以修改文件的状态
   1)open 指定O_NONBLOCK状态
   2)fcntl修改文件描述符状态为O_NONBLOCK
   如果修改为非阻塞,无数据读,或写不进去会马上出错返回,read返回-1,errno值为EAGAIN  
   
三 操作锁的总结
   1.recording locking 其实是byte-range locking 记录(文件)锁
   2 锁功能的历史
     早期: flock 只能锁整个文件,不能锁文件部分
     svr3:  lockf 允许锁部分
     posix: fcntl
     
   3.fcntl的所有功能
      复制现有描述符  F_DUPFD
      获得或设置文件描述符标记  F_GETFD F_SETFD
      获得或设置文件状态标志   F_GETFL F_SETFL   读写模式,阻塞模式,同步异步读写等
      获得或设置异步IO所有权 F_GETOWN F_SETOWN  
      获得或设置记录锁(文件锁)   F_GETLK F_SETLK  F_SETLKW
   4.fcntl记录锁(文件锁)
     第三个参数指向数据结构 struct flock
     a)多个进程锁规则是:只能多个读锁同时存在,不能再加写锁; 只有一个写锁存在,不能再加读锁;
     b)单个进程锁规则是:多次锁操作,会将新锁替换以前的锁
     c)如果多个锁的空间连续,系统就会合并到一个锁。否则拆分成多个锁
   5.锁的继承和释放
     a)进程终止的时候,它所建立的锁全部释放
     b)关闭描述符时,则通过这一描述符引用的文件的所有锁都被释放
     c)fork创建的子进程不继承父进程的锁

     d)如果没对文件描述符设置close-on-exec,那么exec执行后,继承原程序的锁,否则会将原来的锁释放掉

          如果利用F_SETFD设置了FD_CLOEXEC标识,

           那么exec后会将关闭文件描述符,这样避免文件描述符被多个进程使用

fcntl(fd, F_SETFD, FD_CLOEXEC); // 这里设置为FD_CLOEXEC表示当程序执行exec函数时本fd将被系统自动关闭,表示不传递给exec创建的新进程, 如果设置为fcntl(fd, F_SETFD, 0);那么本fd将保持打开状态复制到exec创建的新进程中



     e)文件的尾端加解锁需要小心,文件的长度可能被其他进程修改
     f)建议性锁与强制性锁
       合作进程:使用所有函数都以相同方式处理锁的库的进程
     g)强迫性锁 强制内核对每一个系统调用都进行文件锁的检查(排它锁)
        强制性锁可以被程序ed避开
        对一个文件打开其设置组ID位而关闭其组执行位就开启了强制性锁机制
     h) 系统调用跟踪命令
        solaris  truss
        freebsd和mac os X   ktrace和kdump
        linux  strace
        
四 UNIX V 流streams机制
    1)概念
      流是在用户进程和设备驱动程序之间提供了一条全双工通路
    需要时再细致研究
    
五 多个IO轮询
    1)select
      指定等待时间再返回,参数指定了可读可写及异常的文件描述符
      select 支持最大文件描述符集合1024,
    2)pselect
      同上,但是时间跟细致,可以支持信号屏蔽
    3)poll
      每个数组元素是一个结构体pollfd,里面有期盼的文件描述符状态和实际的文件描述符状态
      pollup后不可以写,但还可以继续读
      pollin输入文件结束标志
    4)epoll
    
六 异步IO

   V中是信号SIGPOLL
   ioctl 设置I_SETSIG,并建立信号处理程序
   
   BSD中
   SIGIO 异步IO信号
   SIGURG 网络有带外数据
   步骤如下:
   1)sigaction建立信号处理程序
   2)以命令F_SETOWN调用fcntl,设置进程id及进程组id
   3)以F_SETFL调用fcntl设置O_ASYNC文件状态标志
   
   1)缺点是: 每个进程只有一个信号,不能识别到多个文件描述符
   
七 readv和writev函数,  readn和writen函数的知识点
   1) readv及writev用于在一个函数中读写多个非连续缓冲区
      减少系统的调用次数,优化时间
   2)readn及writen
     默认的read及write可能返回少于期待的数据量,通常他们不会返回失败,应该做判断并继续读写
     readn及writen实现了这个多次调用满足指定字节数的条件
   3)那如果是自定义封包解析的时候,这样写貌似有问题的哦!
     typedef struct
      {
          unsigned id;
          unsigned flag;
      } io_type;
      if (read(fd, buf, sizeof(io_type)) == sizeof(io_type))
         //这里万一是2次read得到一个包,就球了!
     
八 存储映射IO
  1) 关联映射
   mmap(void* addr, size_t len, int prot, int flag, int fields, off_t off)
   函数返回文件映射到的内存地址的起始位置
   addr 指定内存的起始位置,  如果为0,则系统指定内存
   fields关联到一个打开的文件
   off指定文件内部开始映射的偏移位置
   len映射的字节数
   prot 映射区的操作权限,不能大于文件的最大权限
        PROT_READ  
        PROT_WRITE
        PROT_NONE 不可访问
        PROT_EXEC
   flag 影响存储区的属性
    MAP_FIXED 返回值必须等于addr
    MAP_SHARED 写内存直接写到文件
    MAP_PRIVATE 对映射区的存储操作导致创建该映射文件的一个私有副本,以后的引用都关联到这个副本,而不是原来的文件
  2) 映射到2个信号
    SIGSEGV信号,表示进程访问不可用的存储区, 如果向只读的映射区写入数据则产生该信号
    SIGBUS信号, 表示映射区对于的某个数据不存在了
  3)fork后,子进程继承存储映射区,如果调用了exec就不再继承了
  4)修改映射区的权限
     mprotect
  5)冲洗映射区的内容到文件
    msync(void *, size_t len, int flags)
     flags  = MS_SYNC 等待写完成再返回
  6)解决映射绑定
    munmap

   
  

你可能感兴趣的:(Linux命令,开发工具使用心得,io,linux,locking,存储,freebsd,struct)