非阻塞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\n",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\n",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){
;
}
}
非阻塞io与记录锁的更多相关文章
- Python异步非阻塞IO多路复用Select/Poll/Epoll使用,线程,进程,协程
1.使用select模拟socketserver伪并发处理客户端请求,代码如下: import socket import select sk = socket.socket() sk.bind((' ...
- 转一贴,今天实在写累了,也看累了--【Python异步非阻塞IO多路复用Select/Poll/Epoll使用】
下面这篇,原理理解了, 再结合 这一周来的心得体会,整个框架就差不多了... http://www.haiyun.me/archives/1056.html 有许多封装好的异步非阻塞IO多路复用框架, ...
- Python_阻塞IO、非阻塞IO、IO多路复用
0.承上 进程: 计算机里最小的资源分配单位: 数据隔离, 利用多核,数据不安全. 线程: 计算机中最小的CPU调度单位: 数据共享,GIL锁,数据不安全. 协程: 线程的一部分,是有用户来调度的; ...
- python 全栈开发,Day44(IO模型介绍,阻塞IO,非阻塞IO,多路复用IO,异步IO,IO模型比较分析,selectors模块,垃圾回收机制)
昨日内容回顾 协程实际上是一个线程,执行了多个任务,遇到IO就切换 切换,可以使用yield,greenlet 遇到IO gevent: 检测到IO,能够使用greenlet实现自动切换,规避了IO阻 ...
- Redis——非阻塞IO和队列
Redis是个高并发的中间件,但是确实是单线程.而且,Nginx.Node.js等也是单线程的.Redis通过非阻塞IO(IO多路复用)处理那么多的并发客户端连接,并且,由于Redis所有的数据都在内 ...
- Java网络编程和NIO详解5:Java 非阻塞 IO 和异步 IO
Java网络编程和NIO详解5:Java 非阻塞 IO 和异步 IO Java 非阻塞 IO 和异步 IO 转自https://www.javadoop.com/post/nio-and-aio 本系 ...
- 阻塞IO、非阻塞IO、同步IO、异步IO等
https://www.cnblogs.com/zingp/p/6863170.html 阅读目录 1 基础知识回顾 2 I/O模式 3 事件驱动编程模型 4 select/poll/epoll的区别 ...
- Linux下的非阻塞IO(一)
非阻塞IO是相对于传统的阻塞IO而言的. 我们首先需要搞清楚,什么是阻塞IO.APUE指出,系统调用分为两类,低速系统调用和其他,其中低速系统调用是可能会使进程永远阻塞的一类系统调用.但是与磁盘IO有 ...
- 【python】-- 事件驱动介绍、阻塞IO, 非阻塞IO, 同步IO,异步IO介绍
事件驱动介绍 一.前言 通常,我们写服务器处理模型的程序时,有以下几种模型: (1)每收到一个请求,创建一个新的进程,来处理该请求: (2)每收到一个请求,创建一个新的线程,来处理该请求: (3)每收 ...
随机推荐
- UITableView 的增删改 自定义UITableViewCell
1.UITableView的增删改 //设置编辑模式 [self.tableView setEditing:YES animated:YES]; //可以不写 - (BOOL)tableView:(U ...
- 跨域iframe高度自适应(兼容IE/FF/OP/Chrome)
采用JavaScript来控制iframe元素的高度是iframe高度自适应的关键,同时由于JavaScript对不同域名下权限的控制,引发出同域.跨域两种情况. 由于客户端js使用浏览器的同源安全策 ...
- oracle lsnrctl
Oracle 11G在windows 7系统上不需要设置系统环境变量. 在命令行环境中运行命令: echo %ORACLE_SID% 可以看到此变量并不存在.也可以到注册表验证: HKEY_CURRE ...
- Linux下命令sort, uniq
标题:sort, uniq 一.sort命令的使用 1. 作用:sort命令顾名思意,其可以帮助我们进行排序,而且可以依据不同的数据类型来排序.例如数字和文字的排序就不一样,sort可以指 ...
- 给定数组a[N]构造数组b[N]
转自:http://blog.csdn.net/wumuzi520/article/details/7841280 给定一个数组a[N],我们希望构造数组b [N], 其中b[j]=a[0]*a[1] ...
- 创建App IDs时选择App ID Prefix才能勾选push notifications
- 获取input中的值
先在input标签中添加一个id='getvalue'document.getElementById("getvalue").value;
- Linq To Csv 实例简说
http://www.codeproject.com/Articles/25133/LINQ-to-CSV-library 详细源代码在这里 https://github.com/mperdeck/L ...
- JavaScript之菱形打印
很高兴来到博客园!迈入这座知识的殿堂,实是幸运.这是我的第一篇博客,开启丰富有趣的学习之旅,同时,我希望和大家一起学习一起进步,Let‘s go! <!DOCTYPE html PUBLIC & ...
- C#创建Windows服务入门图解(VS2010)
C#创建Windows服务入门图解(VS2010) Windows服务大家都知道,比如Audio.Theme都是大家比较熟悉的服务,他们可以设为自动启动的,并且在注册表的开机自启动项里是没有痕迹的.所 ...