非阻塞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)每收 ...
随机推荐
- 各种"居中"
先看效果 代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8"/> < ...
- mysql 自增序列(转)
1:原理是在建立一个触发器TRIGGER tri_NewBH 在table插入时执行序列计算 mysql),content ),`date` DATETIME,val INT); Query OK, ...
- ASP.NET Ajax简单的无刷新分页
最近练习了一些AJAX无刷新分页,写得比较简单,性能不知道怎么样,求大神指点,如有更好的分页提供,欢迎交流! 发话不多说了,直接上代码! 首先从网上下了一个JS分页,感觉挺好用的 (function( ...
- Part 4 using entity framework
Step1: Install entity framework using nuget package manager. Step2: Add a class file to the Models f ...
- JOSN传字符串方法
#region 提示信息 /// <summary> /// 操作失败(无参数) /// </summary> /// <returns></returns& ...
- Android渲染机制和丢帧分析
http://blog.csdn.net/bd_zengxinxin/article/details/52525781 自己编写App的时候,有时会感觉界面卡顿,尤其是自定义View的时候,大多数是因 ...
- Google Play支付校验
关于Google Play支付校验我之前在网上也找过大量的相关资料,发现大多数都是采用publicKey的方式来校验订单,但是在Google Play提供的官方实例中publicKey其实在客户端也是 ...
- ES6新增Promise
1.promise概念 ES6 原生提供了 Promise 对象. 所谓 Promise,就是一个对象,用来传递异步操作的消息.它代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个事件提 ...
- 杭电ACM2011-- 多项式求和
题目地址 :多项式求和 /* #include<stdio.h> int main() { int n,b; double a[110],x; double z; int i,j; int ...
- Codevs 1474 十进制转m进制
时间限制: 1 s 空间限制: 128000 KB 题目等级 : 白银 Silver 题目描述 Description 将十进制数n转换成m进制数 m<=16 n<=100 输 ...