书签 分享 收藏 举报 版权申诉 / 66
上传文档赚钱

类型linux教程-第9章-数据的IO和复用课件.pptx

  • 上传人(卖家):ziliao2023
  • 文档编号:5785456
  • 上传时间:2023-05-09
  • 格式:PPTX
  • 页数:66
  • 大小:1.79MB
  • 【下载声明】
    1. 本站全部试题类文档,若标题没写含答案,则无答案;标题注明含答案的文档,主观题也可能无答案。请谨慎下单,一旦售出,不予退换。
    2. 本站全部PPT文档均不含视频和音频,PPT中出现的音频或视频标识(或文字)仅表示流程,实际无音频或视频文件。请谨慎下单,一旦售出,不予退换。
    3. 本页资料《linux教程-第9章-数据的IO和复用课件.pptx》由用户(ziliao2023)主动上传,其收益全归该用户。163文库仅提供信息存储空间,仅对该用户上传内容的表现方式做保护处理,对上传内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知163文库(点击联系客服),我们立即给予删除!
    4. 请根据预览情况,自愿下载本文。本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
    5. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007及以上版本和PDF阅读器,压缩文件请下载最新的WinRAR软件解压。
    配套讲稿:

    如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。

    特殊限制:

    部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。

    关 键  词:
    linux 教程 数据 IO 课件
    资源描述:

    1、9.1 IO函数9.2 使用IO函数的例子9.3 IO模型9.4 select()函数和pselect()函数9.5 poll()函数和ppoll()函数9.6 非阻塞编程掌握:IO函数、select()函数(重点)了解:IO原理(难点)、IO模型9.1.1 使用recv()函数接收数据9.1.2 使用send()函数发送数据9.1.3 使用readv()函数接收数据9.1.4 使用writev()函数发送数据9.1.5 使用recvmsg()函数接收数据9.1.6 使用sendmsg()函数发送数据9.1.7 IO函数的比较3recvmsgrecvitsoreceiverecvitsorec

    2、eive读系统调用的流程4sendmsgsenditsosendrecv()函数用于接收数据。recv()函数从套接字s中接收数据放到缓冲区buf中,buf的长度为len,操作的方式由flags指定。只能用于绑定了来源端地址的套接字。#include#include ssize_t recv(int s,void*buf,size_t len,int flags);send()函数用于发送数据。send()函数将缓冲区buf中大小为len的数据,通过套接字文件描述符按照flags指定的方式发送出去。只能用于绑定了目的地址的套接字。当flags=0时,send()等同于write()。#incl

    3、ude#include ssize_t send(int s,const void*buf,size_t len,int flags);readv()函数可用于将接收的数据分散到多个缓冲区数据。readv()函数从套接字描述符s中读取count块数据放到缓冲区向量vector中。#include ssize_t readv(int s,const struct iovec*vector,int count);writev()函数用于收集多个缓冲区的数据写入套接字。writev()函数向套接字描述符s中写入在向量vector中保存的count块数据。#include ssize_t writev

    4、(int fd,const struct iovec*vector,int count);recvmsg()函数用于接收数据,与recv()函数、readv()函数相比较,这个函数的使用要复杂一些。1函数recvmsg()原型含义2地址结构msghdr3函数recvmsg()用户空间与内核空间的交互recvmsg()从套接字s中接收数据放到缓冲区msg中,操作的方式由flags指定。#include#include ssize_t recvmsg(int s,struct msghdr*msg,int flags);函数recvmsg()中用到结构msghdr的原型如下:struct msgh

    5、dr void *msg_name;/*可选地址*/socklen_t msg_namelen;/*地址长度*/struct iovec*msg_iov;/*接收数据的数组*/size_t msg_iovlen;/*msg_iov中的元素数量*/void *msg_control;/*ancillary data,see below*/socklen_t msg_controllen;/*ancillary data buffer len*/int msg_flags;/*接收消息的标志*/;接收来自接收来自192.168.1.150192.168.1.150的发送到的发送到192.168.1

    6、.151192.168.1.151的的200200个个UDPUDP数据,接收后数据,接收后msghdrmsghdr结构的情况。结构的情况。函数sendmsg()可用于向多个缓冲区发送数据。函数sendmsg()向套接字描述符s中按照结构msg的设定写入数据,其中操作方式由flags指定。#include ssize_t sendmsg(int s,const struct msghdr*msg,int flags);向192.168.1.200端口为9999的主机发送300B数据,将msg参数中的3个向量缓冲区大小都为100,msg状态如图。如何使用sendmsg()函数struct sock

    7、addr_in receiver_addr;/1.定义地址char line15=Hello World!;/2.缓冲区struct msghdr msg;/3.定义msghdrstruct iovec iov;/4.定义iovec /5.各种值的设置msg.msg_name=&receiver_addr;msg.msg_namelen=sizeof(receiver_addr);msg.msg_iov=&iov;msg.msg_iovlen=1;msg.msg_iov-iov_base=line;msg.msg_iov-iov_len=15;msg.msg_control=0;msg.msg

    8、_controllen=0;msg.msg_flags=0;sendmsg(sock_fd,&msg,0);/6.调用该函数表9.8为上述函数使用时的特点,标记的为具有此种属性。有如下规律:表9.8为上述函数使用时的特点,标记的为具有此种属性。有如下规律:函数read()/write()和readv()/writev()可以对所有的文件描述符使用;recv()/send()、recvfrom()/writeto()和recvmsg/sendmsg只能操作套接字描述符。函数readv()/writev()和recvmsg()/sendmsg()可以操作多个缓冲区,read()/write()、r

    9、ecv()/send()和recvfrom()/sendto()只能操作单个缓冲区。函数recv()/send()、recvfrom()/sendto()和recvmsg()/sendmsg()具有可选标志。函数recvfrom()/sendto()和recvmsg()/sendmsg()可以选择对方的IP地址。函数recvmsg()/sendmsg()有可选择的控制信息,能进行高级操作。9.2.1 客户端处理框架的例子9.2.2 服务器端程序框架9.2.3 使用recv()和send()函数9.2.4 使用readv()和writev()函数9.2.5 使用recvmsg()和sendmsg

    10、()函数客户端处理程序是一个程序框架,为后面使用3种类型的收发函数建立基本的架构。1客户端程序框架2客户端程序框架代码图9.6 客户端处理流程29 signal(SIGINT,sig_proccess);/*挂接SIGINT信号,处理函数为sig_process()*/30 signal(SIGPIPE,sig_pipe);/*挂接SIGPIPE信号,处理函数为sig_pipe()*/服务器端处理程序是一个程序框架,为后面使用3种类型的收发函数建立基本的架构。函数process_conn_server()是进行服务器端处理的函数,不同收发函数的实现方式不同。20 signal(SIGINT,s

    11、ig_proccess);/*挂接SIGINT信号,处理函数为sig_process()*/21 signal(SIGPIPE,sig_proccess);/*挂接SIGPIPE信号,处理函数为sig_pipe()*/下面使用recv()和send()函数进行网络数据收发。1服务器端的实现代码2客户端的处理代码3信号SIGINT的处理函数4信号SIGPIPE的处理函数服务器端的处理过程先使用recv()函数从套接字文件描述符s中读取数据到缓冲区buffer中,如果不能接收到数据则退出操作。服务器成功接收数据后,利用接收到的数据构建发送给客户端的响应字符串,调用send()函数将响应字符串发送给

    12、客户端。07for(;)/*循环处理过程*/08size=recv(s,buffer,1024,0);09/*从套接字中读取数据放到缓冲区buffer中*/10if(size=0)/*没有数据*/11return;12.07 for(;)/*循环处理过程*/08size=read(0,buffer,1024);09/*从标准输入中读取数据放到缓冲区buffer中*/10 if(size 0)/*读到数据*/11send(s,buffer,size,0);/*发送给服务器*/12size=recv(s,buffer,1024,0);/*从服务器读取数据*/13write(1,buffer,siz

    13、e);/*写到标准输出*/14 01/*信号SIGINT的处理函数*/02 void sig_proccess(int signo)03 04printf(Catch a exit signaln);05_exit(0);06 01/*信号SIGPIPE的处理函数*/02 void sig_pipe(int sign)03 04printf(Catch a SIGPIPE signaln);0506/*释放资源*/07 使用如下的代码代替9.2.1节中的函数process_conn_client()和9.2.2节中的process_conn_server(),使用readv()和writev(

    14、)进行读写。1服务器端的实现代码2客户端的处理代码3信号SIGINT的处理函数4信号SIGPIPE的处理函数下面是使用readv()和writev()进行数据IO的服务器处理的代码,利用向量来接收和发送网络数据。12 struct iovec*v=(struct iovec*)malloc(3*sizeof(struct iovec);与服务器端的代码类似,客户端也使用3个10字节大小的向量来完成数据的发送和接收操作。01/*信号SIGINT的处理函数*/02 void sig_proccess(int signo)03 04printf(Catch a exit signaln);05/*释

    15、放资源*/06free(vc);07free(vs);08_exit(0);09 01/*信号SIGPIPE的处理函数*/02 void sig_pipe(int sign)03 04printf(Catch a SIGPIPE signaln);0506/*释放资源*/07free(vc);08free(vs);09_exit(0);10 使用如下的代码代替9.2.1节中的函数process_conn_client()和9.2.2节中的process_conn_server()函数,使用recvmsg()和sendmsg()进行读写。1服务器端的实现代码2客户端的处理代码3信号SIGINT的

    16、处理函数4信号SIGPIPE的处理函数在服务器端调用函数recvmsg()从套接字s中接收数据到消息msg中,将接收到的消息进行处理后,调用sendmsg()函数将响应数据通过套接字s发出。与服务器端对应,客户端的实现也将3个向量挂接在一个消息上进行数据的收发操作。注意:缓冲区接收数据前要清0,否则可能出现乱字符。发送前发送缓冲区中的数据字节数要重新设置。01/*信号SIGINT的处理函数*/02 void sig_proccess(int signo)03 04printf(Catch a exit signaln);05/*释放资源*/06free(vc);07free(vs);08_ex

    17、it(0);09 01/*信号SIGPIPE的处理函数*/02 void sig_pipe(int sign)03 04printf(Catch a SIGPIPE signaln);05/*释放资源*/06free(vc);07free(vs);08_exit(0);09 9.3.1 阻塞IO模型9.3.2 非阻塞IO模型9.3.3 IO复用9.3.4 信号驱动IO模型9.3.5 异步IO模型阻塞IO是最通用的IO类型,使用这种模型进行数据接收的时候,在数据没有到之前程序会一直等待。例如对于函数recvfrom(),内核会一直阻塞该请求直到有数据到来才返回。以数据报为例阻塞IO是最通用的IO

    18、类型,使用这种模型进行数据接收的时候,在数据没有到之前程序会一直等待。例如对于函数recvfrom(),内核会一直阻塞该请求直到有数据到来才返回。当把套接字设置成非阻塞的IO,则对每次请求,内核都不会阻塞,会立即返回;当没有数据的时候,会返回一个错误。例如对recvfrom()函数,前几次都没有数据返回,直到最后内核才向用户层的空间复制数据。轮询会消耗大量CPU时间。如果TCP客户端同时处理两个输入:标准输入和TCP套接字。当客户端阻塞于(标准输入上时)(gets调用期间,服务器进程被杀死。服务器TCP虽然正确地给客户TCP发送了一个FIN。但是既然客户进程正阻塞于从标准输入读入的过程,它将看

    19、不到这个EOF,直到从套接字读时为止(可能已过了很长时间)。这样的进程需要一种预先告知内核的能力,使得内核一旦发现进程指定的一个或多个I/O条件就绪(也就是说输入已准备好被读取,或者描述符己能承接更多的输出),它就通知进程。这个能力称为I/O复用(multiplexing),是由select和po11这两个函数支持的。使用IO复用模型可以在等待的时候加入超时的时间,当超时时间没有到达与阻塞的情况一致(但阻塞在select或poll上),而当超时时间到达仍然没有数据接收到,系统会返回,不再等待。select()函数按照一定的超时时间轮询,直到需要等待的套接字有数据到来,利用recvfrom()函

    20、数,将数据复制到应用层。1.比较阻塞I/O与I/O复用,后者的优势在于select可以等待多个描述符就绪。2.与I/O复用密切相关的另一种I/O模型是在多线程中使用阻塞式I/O。两者极为相似,后者使用多个线程(每个文件描述符开一个线程),这样每个线程都可以自由地调用诸如recvfrom之类的阻塞式I/O系统调用了。信号驱动的IO在进程开始的时候注册一个信号处理的回调函数,进程继续执行,当信号发生时,即有了IO的时间,这里即有数据到来,利用注册的回调函数将到来的数据用recvfrom()接收到。异步IO与前面的信号驱动IO相似,其区别在于信号驱动IO当数据到来的时候,使用信号通知注册的信号处理函

    21、数何时启动I/O操作,而异步IO则在数据复制完成的时候才发送信号通知注册的信号处理函数I/O操作何时完成。9.4.1 select()函数9.4.2 pselect()函数参考UNIX环境高级编程2版14.5节函数select()与之前的recv()和send()直接操作文件描述符不同。使用select()函数可以先对需要操作的文件描述符进行查询,查看目标文件描述符是否可以进行读、写或者错误操作,然后当文件描述符满足操作的条件的时候才进行真正的IO操作。1函数select()简介2select()函数的例子函数select()的原型如下:#include#include#include#inc

    22、lude int select(int nfds,fd_set*readfds,fd_set*writefds,fd_set*exceptfds,struct timeval*timeout);the last argument,This specifies how long we want to wait:struct timeval long tv_sec;/*seconds*/long tv_usec;/*and microseconds*/;There are three conditions.tvptr=NULL Wait forever.This infinite wait can

    23、 be interrupted if we catch a signal.Return is made when one of the specified descriptors is ready or when a signal is caught.If a signal is caught,select returns 1 with errno set to EINTR.tvptr-tv_sec=0&tvptr-tv_usec=0 Dont wait at all.All the specified descriptors are tested,and return is made imm

    24、ediately.This is a way to poll the system to find out the status of multiple descriptors,without blocking in the select function.tvptr-tv_sec!=0|tvptr-tv_usec!=0 Wait the specified number of seconds and microseconds.Return is made when one of the specified descriptors is ready or when the timeout va

    25、lue expires.If the timeout expires before any of the descriptors is ready,the return value is 0.(If the system doesnt provide microsecond resolution,the tvptrtv_usec value is rounded up to the nearest supported value.)As with the first condition,this wait can also be interrupted by a caught sig。函数se

    26、lect()监视标准输入是否有数据输入,所设置的超时时间为5s。如果select()函数出错,则打印出错信息;如果标准输入有数据输入,则打印输入信息;如果等待超时,则打印超时信息。15err=select(1,&rd,NULL,NULL,&tv);函数select()是用一种超时轮循的方式来查看文件的读写错误可操作性。在Linux下,还有一个相似的函数pselect()。1pselect()函数简介2pselect()函数的例子 Each process has a signal mask that defines the set of signals currently blocked fr

    27、om delivery to that process.We can think of this mask as having one bit for each possible signal.If the bit is on for a given signal,that signal is currently blocked.A process can examine and change its current signal mask by calling sigprocmask,which we describe in Section 10.12.unix环境高级编程英文版第2版 PO

    28、SIX.1 defines a datatype,called sigset_t,that holds a signal set.The signal mask,for example,is stored in one of these signal sets.pselect()函数的原型如下:#include#include#include#include int pselect(int nfds,fd_set*readfds,fd_set*writefds,fd_set*exceptfds,const struct timespec*timeout,const sigset_t*sigma

    29、sk);在例子中先清空信号,然后将SIGCHLD信号加入到要处理的信号集合中。设置pselect()监视的信号时,在挂载用户信号的同时将系统原来的信号保存下来,方便程序退出的时候恢复原来的设置。We need a data type to represent multiple signals-a signal set.Well use this with such functions as sigprocmask(in the next section)to tell the kernel not to allow any of the signals in the set to occur.

    30、9.5.1 poll()函数9.5.2 ppoll()函数poll()函数等待某个文件描述符上的某个事件的发生。其原型如下:#include int poll(struct pollfd*fds,nfds_t nfds,int timeout);与select()函数和pselect()函数的情况相似,与poll()函数对应的也存在一个ppoll()函数,其定义如下:#include int ppoll(struct pollfd*fds,nfds_t nfds,const struct timespec*timeout,const sigset_t*sigmask);9.6.1 非阻塞方式程

    31、序设计介绍9.6.2 非阻塞程序设计的例子非阻塞方式的操作与阻塞方式的操作最大的不同点是函数的调用立刻返回,不管数据是否成功读取或者成功写入。使用fcntl()将套接字文件描述符按照如下的代码进行设置后,可以进行非阻塞的编程:fcntl(s,F_SETFL,O_NONBLOCK);函数accept()可以使用非阻塞的方式轮询等待客户端的到来,在之前要设置O_NONBLOCK方式。15/*设置非阻塞方式*/16fcntl(s_s,F_SETFL,O_NONBLOCK);1.修改7.2.5节的程序,使服务端和客户端能连续接受和输入10,150,250个字节的字串。至少要三个缓冲区,缓冲区长度不能超过140字节。备注:iov数组中的iov_len每次在接受前后都要处理或发送前也要处理。否则结果可能不是你想象的结果。2.利用select()实现I/O复用方式在同一TCP服务器进程(线程)中实现对多个客户端的数据传输(利用recv()和send())。3.利用多线程的I/O阻塞方式在同一TCP服务器进程中实现对多个客户端的数据传输(利用recvmsg()和sendmsg())。

    展开阅读全文
    提示  163文库所有资源均是用户自行上传分享,仅供网友学习交流,未经上传用户书面授权,请勿作他用。
    关于本文
    本文标题:linux教程-第9章-数据的IO和复用课件.pptx
    链接地址:https://www.163wenku.com/p-5785456.html

    Copyright@ 2017-2037 Www.163WenKu.Com  网站版权所有  |  资源地图   
    IPC备案号:蜀ICP备2021032737号  | 川公网安备 51099002000191号


    侵权投诉QQ:3464097650  资料上传QQ:3464097650
       


    【声明】本站为“文档C2C交易模式”,即用户上传的文档直接卖给(下载)用户,本站只是网络空间服务平台,本站所有原创文档下载所得归上传人所有,如您发现上传作品侵犯了您的版权,请立刻联系我们并提供证据,我们将在3个工作日内予以改正。

    163文库