非阻塞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)每收 ...
随机推荐
- Kinect For Windows V2开发日志九:侦测并绘制人体骨架
简介 在上一篇<侦测.追踪人体骨架>里,介绍了关节点的使用办法,这一篇记录将关节点与OpenCV结合的绘图方法. 代码 #include <iostream> #include ...
- Solr中初学Demo
import java.util.Collection; import java.util.Date; import org.apache.solr.client.solrj.SolrQuery; i ...
- vijos 1053Easy sssp
P1053Easy sssp Accepted 标签:图结构 最短路 描述 输入数据给出一个有N(2 <= N <= 1,000)个节点,M(M <= 100,000)条边的 ...
- MVC 菜鸟学习记录2
自定义Html.Helper扩展方法 在Models文件夹下新建一个静态类,取名为:MyHtmlHelper.cs 将MyHtmlHelper设置为static,并写入以下的一个静态方法 public ...
- OpenFlow概述
OpenFlow名称里面虽然包括“Flow”,但其并不是“又一个流程引擎”,我们认为世界上的流程引擎已经足够多了,每个流程引擎都各有千秋,有的甚至免费,所以我们不需要再做一个流程引擎,我们做OpenF ...
- OpenShare新功能@2014年第三季度
新功能@2014第三季度 新增"多租户"的支持:巨型企业集团的私有云需要多租户模式,现在OpenShare可以从根本上完美支持 租户之间完全隔离,这是最高安全性 同时每个租户可以使 ...
- ListView优化-getView优化
ListView作为Android中最常用的组件之一,其优化方式也比较多. 在使用ListView或是GridView的时候,往往需要自定义数据适配器.一般我们都需要复习getView方法.对于此方法 ...
- html meta标签之http-equiv
摘要:HTTP-EQUIV类似于HTTP的头部协议,它回应给浏览器一些有用的信息,以帮助正确和精确地显示网页内容.常用的HTTP-EQUIV类型有:Content-Type.Refresh .Expi ...
- HTML之调用摄像头实现拍照和摄像功能
应该有很多人知道,我们的手机里面有个功能是“抓拍入侵者”,说白了就是在解锁应用时如果我们输错了密码手机就会调用这一功能实现自动拍照. 其实在手机上还有很多我们常用的软件都有类似于这样的功能,比如微信扫 ...
- JavaScript学习笔记 - 进阶篇(1)- JS基础语法
前言 JavaScript能做什么? 1.增强页面动态效果(如:下拉菜单.图片轮播.信息滚动等) 2.实现页面与用户之间的实时.动态交互(如:用户注册.登陆验证等) JS进阶篇学习什么? 在JavaS ...