非阻塞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与记录锁的更多相关文章

  1. Python异步非阻塞IO多路复用Select/Poll/Epoll使用,线程,进程,协程

    1.使用select模拟socketserver伪并发处理客户端请求,代码如下: import socket import select sk = socket.socket() sk.bind((' ...

  2. 转一贴,今天实在写累了,也看累了--【Python异步非阻塞IO多路复用Select/Poll/Epoll使用】

    下面这篇,原理理解了, 再结合 这一周来的心得体会,整个框架就差不多了... http://www.haiyun.me/archives/1056.html 有许多封装好的异步非阻塞IO多路复用框架, ...

  3. Python_阻塞IO、非阻塞IO、IO多路复用

    0.承上 进程: 计算机里最小的资源分配单位: 数据隔离, 利用多核,数据不安全. 线程: 计算机中最小的CPU调度单位: 数据共享,GIL锁,数据不安全. 协程: 线程的一部分,是有用户来调度的; ...

  4. python 全栈开发,Day44(IO模型介绍,阻塞IO,非阻塞IO,多路复用IO,异步IO,IO模型比较分析,selectors模块,垃圾回收机制)

    昨日内容回顾 协程实际上是一个线程,执行了多个任务,遇到IO就切换 切换,可以使用yield,greenlet 遇到IO gevent: 检测到IO,能够使用greenlet实现自动切换,规避了IO阻 ...

  5. Redis——非阻塞IO和队列

    Redis是个高并发的中间件,但是确实是单线程.而且,Nginx.Node.js等也是单线程的.Redis通过非阻塞IO(IO多路复用)处理那么多的并发客户端连接,并且,由于Redis所有的数据都在内 ...

  6. Java网络编程和NIO详解5:Java 非阻塞 IO 和异步 IO

    Java网络编程和NIO详解5:Java 非阻塞 IO 和异步 IO Java 非阻塞 IO 和异步 IO 转自https://www.javadoop.com/post/nio-and-aio 本系 ...

  7. 阻塞IO、非阻塞IO、同步IO、异步IO等

    https://www.cnblogs.com/zingp/p/6863170.html 阅读目录 1 基础知识回顾 2 I/O模式 3 事件驱动编程模型 4 select/poll/epoll的区别 ...

  8. Linux下的非阻塞IO(一)

    非阻塞IO是相对于传统的阻塞IO而言的. 我们首先需要搞清楚,什么是阻塞IO.APUE指出,系统调用分为两类,低速系统调用和其他,其中低速系统调用是可能会使进程永远阻塞的一类系统调用.但是与磁盘IO有 ...

  9. 【python】-- 事件驱动介绍、阻塞IO, 非阻塞IO, 同步IO,异步IO介绍

    事件驱动介绍 一.前言 通常,我们写服务器处理模型的程序时,有以下几种模型: (1)每收到一个请求,创建一个新的进程,来处理该请求: (2)每收到一个请求,创建一个新的线程,来处理该请求: (3)每收 ...

随机推荐

  1. 各种"居中"

    先看效果 代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8"/> < ...

  2. mysql 自增序列(转)

    1:原理是在建立一个触发器TRIGGER tri_NewBH  在table插入时执行序列计算 mysql),content ),`date` DATETIME,val INT); Query OK, ...

  3. ASP.NET Ajax简单的无刷新分页

    最近练习了一些AJAX无刷新分页,写得比较简单,性能不知道怎么样,求大神指点,如有更好的分页提供,欢迎交流! 发话不多说了,直接上代码! 首先从网上下了一个JS分页,感觉挺好用的 (function( ...

  4. Part 4 using entity framework

    Step1: Install entity framework using nuget package manager. Step2: Add a class file to the Models f ...

  5. JOSN传字符串方法

    #region 提示信息 /// <summary> /// 操作失败(无参数) /// </summary> /// <returns></returns& ...

  6. Android渲染机制和丢帧分析

    http://blog.csdn.net/bd_zengxinxin/article/details/52525781 自己编写App的时候,有时会感觉界面卡顿,尤其是自定义View的时候,大多数是因 ...

  7. Google Play支付校验

    关于Google Play支付校验我之前在网上也找过大量的相关资料,发现大多数都是采用publicKey的方式来校验订单,但是在Google Play提供的官方实例中publicKey其实在客户端也是 ...

  8. ES6新增Promise

    1.promise概念 ES6 原生提供了 Promise 对象. 所谓 Promise,就是一个对象,用来传递异步操作的消息.它代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个事件提 ...

  9. 杭电ACM2011-- 多项式求和

    题目地址 :多项式求和 /* #include<stdio.h> int main() { int n,b; double a[110],x; double z; int i,j; int ...

  10. Codevs 1474 十进制转m进制

    时间限制: 1 s    空间限制: 128000 KB    题目等级 : 白银 Silver 题目描述 Description 将十进制数n转换成m进制数 m<=16 n<=100 输 ...