1. 非阻塞I/O

低速系统调用时可能会使进程永远阻塞的一类系统调用,包括以下调用:
(1)某些文件类型你(网络socket套接字、终端设备、管道)暂无可使用数据,则读操作可能会使调用者永远阻塞
(2)如果数据不能立即被(1)中文件类型接受,则写操作会使调用者永远阻塞
(3)某些进程间通信函数
 
非阻塞I/O使我们可以调用open、read、write这样的I/O操作,并使这些操作不会永远阻塞,如果这种操作不能完成,则调用立即出错返回
 
对于一个给定的文件有两种方法对其指定非阻塞I/O:
(1)调用open打开文件时,指定 O_NONBLOCK标志
(2)对于一个打开的描述符,可以调用fcntl函数,将文件设置为非阻塞I/O
 

2. fcntl记录锁

当一个进程正在读或修改文件的某个部分时,它可以组织其它进程修改同一文件区,它锁定的只是文件的一个区域(也可能是整个文件)
struct flock {
short l_type; /* F_RDLCK, F_WRLCK, F_UNLCK */
off_t l_start; /* offset in bytes, relative to l_whence */
short l_whence; /* SEEK_SET, SEEK_CUR, SEEK_END */
off_t l_len; /* length in bytes, 0 means lock to EOF */
pid_t l_pid; /* returned with F_GETLK */
};
#include <fcntl.h>
int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len)
{
struct flock lock;
lock.l_type = type;
lock.l_start = offset;
lock.l_whence = whence;
lock.l_len = len;
int ret = fcntl(fd, cmd, &lock);
return ret;
}

如果两个进程相互等待对方持有并且锁定的资源时,则这两个进程处于死锁状态

3. select

#include <select.h>
int select(int maxfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, struct timeval* timeout);

中间三个参数 readfds, writefds, exceptfds是指向描述符集的指针,每个描述符集存放在一个fd_set中:

这三个参数指针任意一个可以为空指针,表示对相应状态并不关心。如果三个指针都是空指针,则select提供了比sleep更精确的计时器,因为sleep只能等待整数秒,

而select的struct timeval可以精确到微秒

int  FD_ISSET(int fd, fd_set* set);
void FD_CLR(int fd, fd_set* set);
void FD_SET(int fd, fd_set* set);
void FD_ZERO(fd_set* set);

select的第一个参数maxfds是三个描述符集中最大的fd数值加1,也可以将此参数设置为FD_SETSIZE,表明最大的描述符数

fd_set readset, writeset;
FD_ZERO(&readset);
FD_ZERO(&writeset);
FD_SET(, &readset);
FD_SET(, &readset);
FD_SET(, &writeset);
FD_SET(, &writeset);
select(, &readset, &writeset, NULL, NULL);

因为描述符编号从0开始,所以要在最大描述符编号值加1,第一个参数实际上就是要检查的描述符数(从描述符0开始)

select有3个可能的返回值:
(1)返回值-1表示出错
(2)返回值0表示没有描述符准备好或者超时
(3)返回值为正数表示已经准备好的描述符数,该值是三个描述符集中已准备好的描述符之和,如果同一描述符已经准备好读和写,那么返回值中计为2
 

4. readn和writen

int readn(int fd, char* ptr, size_t n)
{
size_t nleft = n;
int nread = ;
while (nleft > ) {
if ((nread = read(fd, ptr, nleft)) < ) {
if (nleft == n) {
return -;
} else {
break;
}
} else if (nread == ) {
break;
}
nleft -= nread;
ptr += nread;
}
return n - nleft;
}
int writen(int fd, char* ptr, size_t n)
{
size_t nleft = n;
int nwrite = ;
while (nleft > ) {
if ((nwrite = write(fd, ptr, nleft)) < ) {
if (nleft == n) {
return -;
} else {
break;
}
} else if (nwrite == ) {
break;
}
nleft -= nwrite;
ptr += nwrite;
}
return n - nleft;
}
 

5. 存储映射I/O mmap

Memory-mapped I/O 使一个外存磁盘文件与内存空间中的一个缓冲区相映射,当从缓冲区中取数据,就相当于读磁盘文件中的相应字节,写情况亦如此
#include <sys/mman.h>
void* mmap(void* addr, size_t len, int prot, int flag, int fd, off_t off);
addr参数指定映射存储区的起始位置,通常设置为0,表示由内核选择该映射区的起始地址
fd指定被映射文件的描述符,len是映射的字节数,off是映射字节在文件中的起始偏移量
 
addr和off的值通常应当是系统虚拟页长度的倍数,因为addr和off常常指定为0,所以这要求一般不重要
因为映射文件的起始偏移量受系统虚拟页大小限制。假定文件长12字节,系统页长512字节,则系统通常提供512字节的映射区,其中后500字节被设置为0,对该500字节的任何修改都不会在文件中反映出来。
#include <unistd.h>
#include <string.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <sys/types.h>
#include <stdio.h> int main(int argc, char* argv[])
{
int fdin = ;
int fdout = ;
char* src = NULL;
char* dst = NULL;
struct stat statbuf;
if (argc != ) {
fprintf(stderr, "usage: %s <fromfile> <tofile>\n", argv[]);
return ;
}
if ((fdin = open(argv[], O_RDONLY)) < ) {
fprintf(stderr, "cannot open %s for reading\n", argv[]);
}
if ((fdout = open(argv[], O_RDWR | O_CREAT | O_TRUNC)) < ) {
fprintf(stderr, "cannot creat %s for writing\n", argv[]);
}
if (fstat(fdin, &statbuf)) {
fprintf(stderr, "fsat error\n");
} if (lseek(fdout, statbuf.st_size - , SEEK_SET) == -) {
fprintf(stderr, "lseek error\n");
}
if (write(fdout, "", ) != ) {
fprintf(stderr, "write error\n");
} if ((src = mmap(, statbuf.st_size, PROT_READ, MAP_SHARED, fdin, )) == MAP_FAILED) {
fprintf(stderr, "mmap error for input\n");
} if ((dst = mmap(, statbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fdout, )) == MAP_FAILED) {
fprintf(stderr, "mmap error for output\n");
}
memcpy(dst, src, statbuf.st_size);
munmap(src, statbuf.st_size);
munmap(dst, statbuf.st_size);
return ;
}
 
 

APUE 学习笔记(九) 高级I/O的更多相关文章

  1. APUE 学习笔记(十) 高级I/O

    1. Unix IPC(InterProcess Communication) 同一主机的各个进程间的IPC:管道.FIFO.消息队列.信号量.共享存储器 不同主机上的各个进程间IPC:socket套 ...

  2. Hadoop学习笔记(7) ——高级编程

    Hadoop学习笔记(7) ——高级编程 从前面的学习中,我们了解到了MapReduce整个过程需要经过以下几个步骤: 1.输入(input):将输入数据分成一个个split,并将split进一步拆成 ...

  3. 多线程学习笔记九之ThreadLocal

    目录 多线程学习笔记九之ThreadLocal 简介 类结构 源码分析 ThreadLocalMap set(T value) get() remove() 为什么ThreadLocalMap的键是W ...

  4. MDX导航结构层次:《Microsoft SQL Server 2008 MDX Step by Step》学习笔记九

    <Microsoft SQL Server 2008 MDX Step by Step>学习笔记九:导航结构层次   SQL Server 2008中SQL应用系列及BI笔记系列--目录索 ...

  5. python3.4学习笔记(九) Python GUI桌面应用开发工具选择

    python3.4学习笔记(九) Python GUI桌面应用开发工具选择 Python GUI开发工具选择 - WEB开发者http://www.admin10000.com/document/96 ...

  6. Go语言学习笔记九: 指针

    Go语言学习笔记九: 指针 指针的概念是当时学C语言时了解的.Go语言的指针感觉与C语言的没啥不同. 指针定义与使用 指针变量是保存内存地址的变量.其他变量保存的是数值,而指针变量保存的是内存地址.这 ...

  7. APUE学习笔记——10.9 信号发送函数kill、 raise、alarm、pause

    转载注明出处:Windeal学习笔记 kil和raise kill()用来向进程或进程组发送信号 raise()用来向自身进程发送信号. #include <signal.h> int k ...

  8. APUE学习笔记3_文件IO

    APUE学习笔记3_文件IO Unix中的文件IO函数主要包括以下几个:open().read().write().lseek().close()等.这类I/O函数也被称为不带缓冲的I/O,标准I/O ...

  9. matlab学习笔记9 高级绘图命令_2 图形的高级控制_视点控制和图形旋转_色图和颜色映像_光照和着色

    一起来学matlab-matlab学习笔记9 高级绘图命令_2 图形的高级控制_视点控制和图形旋转_色图和颜色映像_光照和着色 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考书籍 < ...

随机推荐

  1. [BZOJ4327]:[JZOI2012]玄武密码(AC自动机)

    题目传送门 题目描述: 在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河.相传一日,一缕紫气从天而至,只一瞬间便消失在了进香河中.老人们说,这是玄武神灵将天书藏匿在此.  ...

  2. js菜鸟备忘

    1.图片切换 function changeImage() { var img = document.getElementById("myImg"); ")) img.s ...

  3. RenderBody,RenderPage和RenderSection

    1. RenderBody 在Razor引擎中没有了“母版页”,取而代之的是叫做“布局”的页面(_Layout.cshtml)放在了共享视图文件夹中.在这个页面中,会看到<body>标签里 ...

  4. untiy3d action管理机制的编写

    使用unity3d对于一些可视化强迫者来说,是一个不错的选择,但unity3d没有cocos2d的action管理机制,比如cocos2dx的CCMoveTo,CCScale等action,所以笔者通 ...

  5. React入门教程(二)

    前言 距离上次我写 React 入门教程已经快2个月了,年头年尾总是比较忙哈,在React 入门教程(一)我大概介绍了 React 的使用和一些注意事项,这次让我们来继续学习 React 一. Rea ...

  6. NOIP2013 乌龟棋

    描述 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游戏要求玩家控制一个乌龟棋子从起点出发走到终点 ...

  7. 【bitset 技巧 分块】bzoj5087: polycomp

    神仙zq发现了${n^2\sqrt n}\over 32$做法 Description 你有三个系数为0,1的多项式f(x),g(x),h(x) 求f(g(x)) mod h(x) 为方便起见,将答案 ...

  8. 【动态规划】51nod1780 完美序列

    巧妙的转化:f前两维大小开反TLE了一发…… 如果一个序列的相邻两项差的绝对值小于等于1,那么我们说这个序列是完美的. 给出一个有序数列A,求有多少种完美序列排序后和数列A相同. Input 第一行一 ...

  9. vmware虚拟机安装Windows 7后虚拟机自动挂起

    vmware虚拟机安装windows7后在一段时间中没有操作,虚拟机会自动挂起,是因为windows7中的设置的自动睡眠,打开[控制面板]=>[电源选项]=>[选择关闭显示器时间]将下面两 ...

  10. JQ之$.ajax()方法以及ajax跨域请求

    AJAX(Asynchronous javascript AND xml :异步javascript和xml):是一种创建交互式网页应用的网页开发技术.AJAX可以在不重新加载整个页面的情况下与服务器 ...