Linux为多路复用IO提供了较多的接口,有select(),pselect(),poll()的方式,继承自BSD和System V 两大派系。

  select模型比较简单,“轮询”检测fd_set的状态,然后再采取相应的措施。

  信号驱动模型有必要仔细研究一下,一般有如下步骤:

  1. 设置安装函数,信号是驱动信号是SIGIO(最好使用sigaction的方式,方便设置flag为SA_RESTART,因为client中读取终端的syscall可能会被中断,有必要重启。当然,使用signal()的方式然后再对errno进行判断是否为ETNTR,自行重启也是一种方法。但是signal()的可移植性问题,我强烈不建议使用)
  2. 设置fd的属主。F_SETOWN,要接受信号的进程,fcntl().
  3. 设置fd的异步标志。小细节,用'|'添加,要把之前的状态保留,也就是先F_GETFL再F_SETFL。(注意:在打开文件open()时设置标识O_ASYNC无实质效果)  

    On Linux, specifying the O_ASYNC
    flag when calling open() has no effect. To enable signal-driven I/O, we must
    instead set this flag using the fcntl() F_SETFL operation (Section 5.3).————《the linux programming interface》 4.3.1

  4. sigaction()安装

  具体进下文client例程。

  写了一个聊天程序的demo,把这两种技术都使用了。服务端采取多路复用的IO方式,代替多进(线)程的模型,客服端采取的是信号驱动,如下:

容易产生bug的地方都写注释里边了。

serv.c

 #include <sys/select.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <signal.h> void endServ(int sig)
{
printf("Server ended!\n");
exit(-);
} int main()
{
// signal
struct sigaction act;
sigemptyset(&act.sa_mask);
act.sa_handler = endServ;
act.sa_flags = ;
sigaction(SIGINT,&act,);
printf("This server is started,enter CTRL+C to end. \n"); int servfd = socket(AF_INET,SOCK_STREAM,);
if(servfd == -) {
printf("something wrong with socket():%m\n");
exit(-);
} struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons();
inet_pton(AF_INET,"127.0.0.1",&addr.sin_addr); if (bind(servfd,(struct sockaddr*)&addr,sizeof(addr)) == -) {
printf("Some thing wrong with bind():%m\n");
exit(-);
}
printf("Bind success!\n"); listen(servfd,); int numbers=;//how many clients has accepted
fd_set fs;
FD_ZERO(&fs);
int client_fd[];
int i;
for(i=;i<;++i)
{
client_fd[i] = -;
} int maxfd=;
char buf[];
for(;;)
{
maxfd =;
FD_ZERO(&fs);
FD_SET(servfd,&fs);
maxfd = maxfd>servfd?maxfd:servfd;
for(i=;i<numbers;++i)
{
if(client_fd[i] != -) {
FD_SET(client_fd[i],&fs);
maxfd = maxfd>client_fd[i]?maxfd:client_fd[i];
}
} int res = select(maxfd+,&fs,,,);
if(res == -) {
printf("Something wrong with select():%m\n");
exit(-);
} if(FD_ISSET(servfd,&fs) && numbers < ) {
printf("New client!\n");
client_fd[numbers] = accept(servfd,,);
numbers++;
} for(i=;i<numbers;++i)
{
bzero(buf,sizeof(buf));
//judge if client_fd[i] equal -1 is necessary
//if a client quited,next time the program will
//have a segment default
//also it should be in the front.
if(client_fd[i] != - && FD_ISSET(client_fd[i],&fs))
{
res = recv(client_fd[i],buf,sizeof(buf),);
if(res == ) {
printf("A client quit\n");
close(client_fd[i]);
FD_CLR(client_fd[i],&fs);
client_fd[i] = -;
}
else if(res == -) {
printf("Something wrong with net.\n");
exit(-);
}
else {
int j;
for(j=;j<numbers;++j)
{
if(client_fd[j] != -)
send(client_fd[j],buf,sizeof(buf),);
}
}
}
}
}
}

client:

 #include <signal.h>
#include <unistd.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h> static int fd; void show(int sig)
{
char buf[] = {};
int n = read(fd,buf,sizeof(buf));
buf[n] = ;
write(,"MSG:",strlen("MSG:"));
write(,buf,strlen(buf));
} int main()
{
struct sigaction act;
sigemptyset(&act.sa_mask);
act.sa_handler = show;
//This is necessary,in last loop read() counld be interrupt;
act.sa_flags = SA_RESTART;
sigaction(SIGIO,&act,); fd = socket(AF_INET,SOCK_STREAM,);
if(fd == -) {
printf("Cannot get socketfd!:%m\n");
exit(-);
} struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons();
inet_pton(AF_INET,"127.0.0.1",&addr.sin_addr); if(connect(fd,(struct sockaddr*)&addr,sizeof(addr)) != -)
printf("connect success!\n");
else
exit(-); int flag = fcntl(fd,F_GETFL);
flag |= O_ASYNC;
fcntl(fd,F_SETFL,flag);
fcntl(fd,F_SETOWN,getpid()); char buffer[]={};
for(;;)
{
int n = read(,buffer,sizeof(buffer));
if(n==-)
break;
send(fd,buffer,n,);
} write(,"Closed.",strlen("Closed."));
}

IO的多路复用和信号驱动的更多相关文章

  1. 《Linux/UNIX系统编程手册》第63章 IO多路复用、信号驱动IO以及epoll

    关键词:fasync_helper.kill_async.sigsuspend.sigaction.fcntl.F_SETOWN_EX.F_SETSIG.select().poll().poll_wa ...

  2. 【网络IO系列】IO的五种模型,BIO、NIO、AIO、IO多路复用、 信号驱动IO

    前言 在上一篇文章中,我们了解了操作系统中内核程序和用户程序之间的区别和联系,还提到了内核空间和用户空间,当我们需要读取一条数据的时候,首先需要发请求告诉内核,我需要什么数据,等内核准备好数据之后 , ...

  3. 【死磕NIO】— 阻塞IO,非阻塞IO,IO复用,信号驱动IO,异步IO,这你真的分的清楚吗?

    通过上篇文章([死磕NIO]- 阻塞.非阻塞.同步.异步,傻傻分不清楚),我想你应该能够区分了什么是阻塞.非阻塞.异步.非异步了,这篇文章我们来彻底弄清楚什么是阻塞IO,非阻塞IO,IO复用,信号驱动 ...

  4. IO模型浅析-阻塞、非阻塞、IO复用、信号驱动、异步IO、同步IO

    最近看到OVS用户态的代码,在接收内核态信息的时候,使用了Epoll多路复用机制,对其十分不解,于是从网上找了一些资料,学习了一下<UNIX网络变成卷1:套接字联网API>这本书对应的章节 ...

  5. Linux 网络编程的5种IO模型:信号驱动IO模型

    Linux 网络编程的5种IO模型:信号驱动IO模型 背景 上一讲 Linux 网络编程的5种IO模型:多路复用(select/poll/epoll) 我们讲解了多路复用等方面的知识,以及有关例程. ...

  6. 信号驱动IO

    [1]信号驱动IO 应用程序:1)应用程序要捕捉SIGIO信号           signal(SIGIO, handler); 2)应用程序要指定进程为文件的属主,设置当前的文件描述为当前的调用进 ...

  7. 🍛 餐厅吃饭版理解 IO 模型:阻塞 / 非阻塞 / IO 复用 / 信号驱动 / 异步

    IO 概念 一个基本的 IO,它会涉及到两个系统对象,一个是调用这个 IO 的进程对象,另一个就是系统内核 (kernel).当一个 read 操作发生时,它会经历两个阶段: 通过 read 系统调用 ...

  8. UDP信号驱动IO

    SIGIO信号 信号驱动式I/O不适用于TCP套接字, 因为产生的信号过于频繁且不能准确判断信号产生的原因. 设置信号驱动需把sockfd的非阻塞与信号驱动属性都打开 server sockfd单独提 ...

  9. Linux IO模式-阻塞io、非阻塞io、多路复用io

    一 概念说明 在进行解释之前,首先要说明几个概念: - 用户空间和内核空间 - 进程切换 - 进程的阻塞 - 文件描述符 - 缓存 I/O 用户空间与内核空间 现在操作系统都是采用虚拟存储器,那么对3 ...

随机推荐

  1. GJM :Unity 使用SqlServer数据库 [原创]

    感谢您的阅读.喜欢的.有用的就请大哥大嫂们高抬贵手"推荐一下"吧!你的精神支持是博主强大的写作动力以及转载收藏动力.欢迎转载! 版权声明:本文原创 ,未经作者同意必须保留此段声明! ...

  2. Rational Rose :从用例图开始

    前置条件:安装Rational Rose 2003 找开Rose工具,选择用例视图  Use Case View 先看看这个视图下面都有哪些工具,都能做一些什么: 下面详细说一下: 用例视图下面有工具 ...

  3. Subway Icon Set – 306个像素完美的特制图标

    这个图标集是306个优化的像素完美,精雕细琢的图标.为这些设备进行了优化:iOS.Windows Phone.Windows 8 and BlackBerry 10,提供 PNG, SVG, XALM ...

  4. 自动适应iframe右边的高度

    在开发项目过程中,用iframe嵌套,会发现一个问题,用iframe嵌套的html结构右边不会自动适应高度. 这时候找到了一个解决方法: <iframe name="my_iframe ...

  5. 【web前端面试题整理07】我不理解表现与数据分离。。。

    拜师传说 今天老夫拜师了,老夫有幸认识一个JS高手,在此推荐其博客,悄悄告诉你,我拜他为师了,他承诺我只收我一个男弟子..... 师尊刚注册的账号,现在博客数量还不多,但是后面点会有干货哦,值得期待. ...

  6. 定制Eclipse IDE之界面篇

    为什么要定制IDE?      在工作时候,当公司有了自己的框架,给自己开放人员用,甚至是可以卖的时候,我们可以做成一个产品,而这个产品将包括框架本身.文档.工具.教程等等.工具之中最重要的莫过于开发 ...

  7. 【Leafletjs】7.结合echart图表展示信息

    1.popup中添加图表信息 //定义marker var marker = L.marker(val.location).addTo(map); var content = '<div sty ...

  8. Android Handler机制(一)---Message源码分析

    Message: 定义: public final class Message implements Parcelable Message类是个final类,就是说不能被继承,同时Message类实现 ...

  9. 查看Android系统是User模式还是Eng模式

    root@itek82_wet_kk:/ # cat default.prop # # ADDITIONAL_DEFAULT_PROPERTIES # ro.secure= ro.allow.mock ...

  10. 【CoreData】 简单地使用

    先介绍一下什么是CoreData —— 它是在iOS5之后出现的一个框架,提供了对象-关系映射(ORM)的功能,既能够将OC对象转化成数据,保存在SQLite数据库文件中,也能将保存在数据库中的数据还 ...