UNIX高级编程-高级I/O

第14章高级I/O

14.1 非阻塞I/O

高级I/O:非阻塞I/O、记录锁、系统V流机制、I/O多路转接、readv和writev函数以及存储映射I/O

低速系统调用可能会永远阻塞进程:

1) 某些文件(管道、终端设备、网络设备)的数据不存在,读操作会导致调用者永远阻塞

2) 数据不能立即被上述同样类型的文件接受,写操作会导致调用者永远阻塞

3) 在某种条件发生之前,打开某些类型的文件会被阻塞

4) 对已经加上强制性记录锁的文件进行读写

5) 某些ioctl操作

6) 某些进程间通信函数

 

对于给定的文件描述符有两种方法对其指定非阻塞I/O

1) 调用open获得文件描述符,指定O_NONBLOCK标志

2) 对于已经打开的文件描述符,调用fcntl,打开O_NONBLOCK文件状态标志

 

14.2 记录锁

功能:当某个进程正在读/写文件的某部分时,可以阻止其他进程修改同一文件区。

Int fcntl(int filedes.,int cmd,/*structflock *flockptr */);

Cmd:F_GETLK、F_SETLK、F_SETLKW

Struct flock{

Short l_type;  //共享读锁,独占性写锁,解锁

Off_t l_start;  //加锁或者解锁文件区域的其实字节偏移量

Short l_whence;//SEEK_SET,SEEK_CUR,orSEEK_END

Off_t l_len; //文件区域的字节长度

Pid_t l_pid;//能阻塞当前进程的锁的进程号,返回F_GETLK

}

F_GETLK:判断flockptr所描述的锁是否被另一把锁排斥

F_SETLK:设置flockptr所描述的锁

F_SETLKW:F_SETLK的阻塞版本

通过将l_start设置为0,whence设置为SEEK_SET可以锁住整个文件,多个进程访问同一个文件时,新锁会替换旧锁,当加读锁时,文件描述符必须为读打开,当加写锁时,文件描述符必须写打开

死锁产生的情况:当两个进程相互等待对方持有并锁定的资源时

 

锁的隐含继承与释放:

1) 进程终止,则它所建立的全部锁会释放;当关闭任意文件描述符,其引用的文件上的全部锁释放

2) Fork产生的子进程不继承父进程设置的锁

3) 执行exec后,新程序可以继承原执行程序的锁。

 

建议性锁和强制性锁

强制性锁会对每个read,write,open系统调用都会进行检查,检查调用进程对访问的文件是否违背了某一把锁的作用

14.4 STREAMS

STREAMS(流)是系统V提供的构造内核设备驱动程序和网络协议包的一种通用方法,流首可以压入处理模块,可以通过ioctl命令实现,所有的STREAMS设备都是字符特殊文件。

 

流首和用户进程的输入和输出都基于消息,并使用read,write,ioctl,getmsg,getpmsg,putmsg和putpmsg交换消息

struct strbuf{

int maxlen;

int len;

char *buf;

}

消息的类型分为三种,M_DATA(I/O用户数据),M_PROTO(协议控制信息),M_PCPROTO(高优先级协议控制信息),每个STREAMS模块有两个输入队列,流的方向正好相反。

 

STREAMS ioctl操作:
int isastream(int filedes); //判断一个描述符是否引入了流

Int ioctl(int filedes,int cmd,…) ;//对设备的I/O通道进行管理

int putmsg(int filedes,const struct strbuf *ctlptr,const structstrbuf *dataptr,int flag);//STREAMS消息写入流

int putpmsg(int filedes,const struct strbuf *ctlptr,const structstrbuf *dataptr,int band,int flag);//可以设置优先级

int getmsg(int filedes,struct strbuf *restrict ctlptr,structstrbuf *restrict dataptr,int *restrict flagptr);//返回流首读队列的下一个消息

int getpmsg(int filedes,struct strbuf *restrict ctlptr,structstrbuf *restrict dataptr,int *restrict bandptr,int *restrict flagptr);

 

1)写模式:request设置为I_GWROPT(该流的当前写模式在第三个参数中返回),若request设置为I_SWROPT(则第三个参数成为该流的新的写模式)

写模式值包括

SNDZERO:0长度写不发送消息

SNDPIPE:当流已出错后,若调用write或者putmsg则调用进程发送SIGPIPE信号

2) 读模式:默认是字节流模式(忽略流中消息的边界),调用ioctl时request设置为I_GRDOPT和I_SRDOPT与写模式作用相似。

读模式值包括:

RNORM:普通,字节流模式

RMSGN:消息不丢弃模式,某次读取一部分,则剩余一部分消息仍保留在流中

RMSGD:消息丢弃模式,某次读一部分,则另一部分丢弃

 

14.5 I/O多路转接

异步I/O基本思想是进程告诉内核,当一个描述符准备好时,用一个信号通知它。

I/O多路转接:先构造一张有关描述符的列表,然后调用一个函数,直到这些描述符中的一个已经准备好进行I.O时,返回告诉进程哪些描述符已经准备好进行I/O。

#include <sys/select.h>

Int select(int maxfdp1,fd_set *restrictreadfds,fd_set *restrict writefds,fd_tset *restrict exceptfds,struct timeval*restrict tvptr);

tvptr:NULL一直等待直到捕捉到一个信号或者描述符中的一个已经准备好;tvptr->tv_sec==0&&tvptr->tv_usec==0完全不等待(测试所有描述符并立即返回)

readfds,writefds,exceptfds可读,可写或者处于异常条件的各个描述符

maxfdp1;在三个fd_set中找到最大的描述符+1

返回值:-1出错,0没有准备好的描述符,其他则是准备好的文件描述符

 

Poll函数类似于select,与STREAMS系统息息相关

#include <poll.h>

Int poll(struct pollfd fdarray[],nfds_tnfds,int timeout);

struct poolfd{

int fd;

short events;//告诉内核描述符关心的事件

short revents;  //返回时,内核设置revents成员说明描述符发生了什么事件

}

Nfds:第一个数组包含多少个元素

当一个描述符被挂断后(POLLHUP),就不能再写向该描述符,但可以读

 

异步I/O:系统V中的异步I/O信号是SIGPOLL;BSD系统中的异步I/O信号是SIGIO和SIGURG

 

Readv(散布读)和writev(聚集写)

#include <sys/uio.h>

Ssize_t readv(int filedes,const structiovec *iov,int iovcnt);

Struct iovec{

Void *iov_base;  //缓冲区起始地址

Size_t iov_len;  //缓冲区长度

}

Ssize_t writev(int filedes,const structiovec *iov,int iovcnt);(适合一次写大量数据)

Ssize_t readn(int filedes,void *buf,size_tnbytes);  //从文件中读N个字节数据

Ssize_t written(int filedes,void*buf,size_t nbytes);//从文件中写N个字节数据

 

存储映射I/O

将文件与缓冲区映射在一起,读/写缓冲区相当于读/写文件

#include<sys/mman.h>

Void *mmap(void *addr,size_t len,intprot,int flag,int filedes,off_t off);

addr:映射区的起始地址

filedes:被映射的文件的描述符

len:映射的字节数

off:映射字节在文件中的起始偏移量

prot:对映射存储区域的保护要求,PROT_READ(映射区可读),PROT_WRITE(映射区可写),PROT_EXEC(映射区可执行),PROT_NONE(映射区不可访问),不超过open的权限

flag:设置不同标志

int mprotect(void *addr,size_t len,int prot);//更改现有映射区的权限

int msync(void *addr,size_t len,int flags);//flags有两种选择,MS_ASYNC标志简化被写页的调度,如果希望返回之前等待写操作完成则设置为MS_SYNC标志,将共享存储区中的已修改数据冲洗至文件中

int munmap(caddr_t addr,size_t len);//解除映射关系


本书全面介绍了UNIX系统的程序设计界面—系统调用界面和标准C库提供的许多函数。 本书的前15章着重于理论知识的阐述,主要内容包括UNIX文件和目录、进程环境、进程控制、 进程间通信以及各种I/O。在此基础上,分别按章介绍了多个应用实例,包括如何创建数据库函数库, PostScript 打印机驱动程序,调制解调器拨号器及在伪终端上运行其他程序的程序等。 本书内容丰富权威, 概念清晰精辟,一直以来被誉为UNIX编程的“圣经”,对于所有UNIX程序员—无论是初学者还是专家级人士 —都是一本无价的参考书籍。 目 录 译者序 译者简介 前言 第1章 UNIX基础知识 1 1.1 引言 1 1.2 登录 1 1.2.1 登录名 1 1.2.2 shell 1 1.3 文件和目录 2 1.3.1 文件系统 2 1.3.2 文件名 2 1.3.3 路径名 2 1.3.4 工作目录 4 1.3.5 起始目录 4 1.4 输入和输出 5 1.4.1 文件描述符 5 1.4.2 标准输入、标准输出和标准 出错 5 1.4.3 不用缓存的I/O 5 1.4.4 标准I/O 6 1.5 程序和进程 7 1.5.1 程序 7 1.5.2 进程和进程ID 7 1.5.3 进程控制 7 1.6 ANSI C 9 1.6.1 函数原型 9 1.6.2 类属指针 9 1.6.3 原始系统数据类型 10 1.7 出错处理 10 1.8 用户标识 11 1.8.1 用户ID 11 1.8.2 组ID 12 1.8.3 添加组ID 12 1.9 信号 12 1.10 UNIX时间值 14 1.11 系统调用和库函数 14 1.12 小结 16 习题 16 第2章 UNIX标准化及实现 17 2.1 引言 17 2.2 UNIX标准化 17 2.2.1 ANSI C 17 2.2.2 IEEE POSIX 18 2.2.3 X/Open XPG3 19 2.2.4 FIPS 19 2.3 UNIX实现 19 2.3.1 SVR4 20 2.3.2 4.3+BSD 20 2.4 标准和实现的关系 21 2.5 限制 21 2.5.1 ANSI C限制 22 2.5.2 POSIX限制 22 2.5.3 XPG3限制 24 2.5.4 sysconf、pathconf 和fpathconf 函数 24 2.5.5 FIPS 151-1要求 28 2.5.6 限制总结 28 2.5.7 未确定的运行时间限制 29 2.6 功能测试宏 32 2.7 基本系统数据类型 32 2.8 标准之间的冲突 33 2.9 小结 34 习题 34 第3章 文件I/O 35 3.1 引言 35 3.2 文件描述符 35 3.3 open函数 35 3.4 creat函数 37 3.5 close函数 37 3.6 lseek函数 38 3.7 read函数 40 3.8 write函数 41 3.9 I/O的效率 41 3.10 文件共享 42 3.11 原子操作 45 3.11.1 添加至一个文件 45 3.11.2 创建一个文件 45 3.12 dup和dup2函数 46 3.13 fcntl函数 47 3.14 ioctl函数 50 3.15 /dev/fd 51 3.16 小结 52 习题 52 第4章 文件和目录 54 4.1 引言 54 4.2 stat, fstat和lstat函数 54 4.3 文件类型 55 4.4 设置-用户-ID和设置-组-ID 57 4.5 文件存取许可权 58 4.6 新文件和目录的所有权 60 4.7 access函数 60 4.8 umask函数 62 4.9 chmod和fchmod函数 63 4.10 粘住位 65 4.11 chown, fchown和 lchown函数 66 4.12 文件长度 67 4.13 文件截短 68 4.14 文件系统 69 4.15 link, unlink, remove和rename 函数 71 4.16 符号连接 73 4.17 symlink 和readlink函数 76 4.18 文件的时间 76 4.19 utime函数 78 4.20 mkdir和rmdir函数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值