文件描述符

UNIX整理

匿名 (未验证) 提交于 2019-12-03 00:33:02
《UNIX程序设计》期末考试复习提纲 题型: 复习要点: (1)什么是操作系统?什么是UNIX操作系统?什么是Linux操作系统?它们之间的关系是怎样的? 操作系统:控制计算机硬件和软件资源,对作业进行合理的调度,以供用户方便使用的一组软件的集合。 UNIX操作系统,是一个强大的多用户、多任务 操作系统 ,支持多种 处理器架构 ,按照操作系统的分类,属于 分时操作系统 。 类Unix 操作系统 ,是一个基于 POSIX 和 UNIX 的多用户、 多任务 、支持 多线程 和多 CPU 的操作系统。 Linux继承了 Unix 以 网络 为核心的设计思想,它能运行主要的UNIX工具软件、应用程序和网络协议。 (2)程序运行时,堆栈如何变化?什么是数据帧或活动记录?bp和sp指针在函数运行过程中是如何变化的? 新的栈中变量会在低地址的位置,新的堆中的变量会在高地址的位置 栈是向低地址延伸的,堆是向高地址延伸的 过程活动记录/栈帧, 每个(用户)栈帧包括如下内容: 函数实参和局部变量:由于这些变量都是在调用函数时自动创建的,因此在C语言中称其为自动变量。函数返回时将自动销毁这些变量(因为栈帧会被释放),这也是自动变量和静态(以及全局)变量主要的语义区别:后者与函数执行无关,且长期存在。 函数调用的链接信息:每个函数都会用到一些CPU寄存器,比如程序计数器,其指向下一条将要执行的机器语言指令

IO多路转接------select

匿名 (未验证) 提交于 2019-12-03 00:32:02
五种IO模型 一文中介绍了五种IO模型。在数据通信过程中,分为两部分:一个是等待数据到达内核,一个是将数据从内核拷贝到用户区。在实际应用中,等待的时间往往比拷贝的时间多,所以要提高IO的效率,就要减少等的比重。在阻塞IO,非阻塞IO,信号驱动IO和异步IO中,虽然等待的方式或等待的主体不同,但是无论是谁在等,无论如何等,等待的时间总长是不变的。 五种IO模型 一文中提到,在服务器与客户端进行通信时,服务器要处理多客户端的情形。所以服务器程序首先要使用selcet等系统调用一次等待多个文件描述符,当至少有一个文件描述符满足就绪条件时,select返回,然后进程调用read对满足就绪条件的文件描述符进行读写。将满足就绪条件的所有文件描述符处理完之后,之前的客户端可能还会再次发送消息,所以,此时就需要不断调用select来循环式的等待满足就绪条件的文件描述符,然后对其进行处理。 select #include <sys/select.h> int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout); 参数说明: nfds :表示一次等待的文件描述符的个数加1;用于限定操作系统遍历的区间 fd_set :该结构实际是一个位图,因为文件描述符其实是数组下标

libco协程库原理解析与应用

匿名 (未验证) 提交于 2019-12-03 00:26:01
最近在准备一个libco协程库原理简析与应用的分享,顺便就整理下写个博客,一方面加深下自己对协程库的理解,另一方面也希望能对想了解协程的学者有所帮助。废话不多说了,言归正传吧。 想去剖析libco协程库的实现原理,首先我们要了解下什么是协程。维基百科上给协程的定义是协程(coroutine)又称微线程,是一个无优先级的子程序(函数)调度组件,允许子程序在特定的地方挂起和恢复。我们可通过一个例子来理解下这句话的意思。函数调用大家都很熟悉吧,下面的这个是一个函数调用的例子。 我们可以很容易的看出函数执行的结果是1 2 3 x y z。而协程的定义说是函数调度组件,但不同的是允许子程序在特定的地方挂起和恢复。也就是调用A函数时可以执行到一半然后挂起去执行B函数,之后可以从A函数挂起的地方继续执行,例如下面的例子: 这个程序执行的结果是1 2 x 3 y z。从这个例子中我们可以对协程的定义有个很清晰的认识了。 了解了协程的定义,那么我们为什么需要协程呢,协程有什么的作用呢,接下来我们来看下协程的由来 起初人们喜欢同步编程,然后发现有一堆线程因为I/O卡在那里,并发上不去,资源严重浪费。 网络服务器模型一般为while(1){accept(); read(); do(); send()}。 然后出了异步(select,epoll,kqueue,etc),将I/O操作交给内核线程

3.文件IO-文件描述符与lseek

匿名 (未验证) 提交于 2019-12-03 00:26:01
文件描述符 在上一篇博客当中,我们知道open函数会返回一个整数,它在本进程中唯一标识了一个文件; 在一个进程中,存在着一个大数组,记录了打开的文件;这个数组的索引就是open函数返回的整数,而这个索引就是 文件描述符 ;而这个数组的每一项,都记录了与打开的文件相关的信息; 在操作系统当中,是通过进程控制块(PCB)来描述进程信息和相关资源的;实际上在Linux中,PCB就是一个巨大的结构体,即task_struct结构体; struct task_struct { long pid ; //进程号 .... //文件描述符标志位 unsigned long close_on_exec ; //数组索引号就是文件描述符;NR_OPEN的值在linux 0.11 中被定义为20 struct file * filp [ NR_OPEN ]; .... }; 上面的PCB结构体中,有一个struct file类型的数组 filp[NR_OPEN]; //struct file记录了文件的相关信息 struct file { unsigned short f_mode ; // 文件权限位 unsigned short f_flags ; // 文件状态位 unsigned short f_count ; // 引用计数 struct m_inode * f_inode ; //

I/O多路转接---epoll服务器

匿名 (未验证) 提交于 2019-12-03 00:26:01
epoll是改进的poll,几乎结合了poll的所有优点,并将poll的缺点加以改进,被公认为Linux2.6下性能最好的多路I/O就绪通知方法。 红黑树结点内容,保存了用户想要告诉操作系统要监控的哪些文件描述符上的哪些事件。 回调机制不需要操作系统一直在等,在事件就绪时,驱动会告诉操作系统,有事件就绪了,操作系统就会处理眼前的事件。这个回调机制在内核中称为epollcallback,它将发生的事件添加到rdlist 在事件就绪后,操作系统将对应的文件描述符上的事件的结点放在就绪队列中,由用户检查就绪队列,来判断是否有事件就绪。 如下图所示: epoll_create #include <sys/epoll.h> int epoll_create( int size); 功能:创建一个epoll的句柄。(即创建epoll模型) 说明: * 从Linux2.6.8之后,size参数是被忽略的。 * 使用完后,必须调用close()关闭。 epoll_ctl #include <sys/epoll.h> int epoll_ctl( int epfd, int op, int fd, struct epoll_event * event ); 功能:epoll的事件注册函数。 说明: * 在监听事件前,要先注册监听什么类型的事件. * 第一个参数epfd是epoll的句柄. *

poll源码剖析

匿名 (未验证) 提交于 2019-12-03 00:25:02
民意调查系统调用,是在指定时间内轮询一定数量的文件描述符,以测试是否有就绪者。 民意调查系统调用原型: #include <poll.h> int poll ( struct follfd * fds , nfds_t nfds , int timeout ); ・ fds参数是一个pollfd结构类型的数组,指定所有感兴趣的文件描述符上发生的可读,可写和异常等事件。 ・ nfds参数指定被监听事件集合fds的大小。 typedef unsigned long int nfds_t; ・ timeout参数指定poll的超时值,单位是毫秒。 当超时为-1时,轮询调用将一直阻塞,直到某个事件发生;当超时为0时,轮询调用立即返回。 基本数据结构 一个pollfd结构类型的数组,指定所有感兴趣的文件描述符上发生的可读,可写和异常等事件。 FD是文件描述符;事件是注册的事件,即监听FD上的事件; revents中是指实际发生的事情,由内核填充。 struct pollfd { int fd ; 短时间事件; 短暂的启示; }; poll_wqueues: struct poll_wqueues { poll_table pt ; struct poll_table_page * table ; int 错误; }; poll_wqueues: struct poll_wqueues {

UNIX环境高级编程――select、poll和epoll

匿名 (未验证) 提交于 2019-12-03 00:22:01
转自: https://blog.csdn.net/ctthuangcheng/article/details/9332431 一、select select目前几乎在所有的平台上支持,其良好跨平台支持也是它的一个优点,事实上从现在看来,这也是它所剩不多的优点之一。 select的一个缺点在于单个进程能够监视的文件描述符的数量存在最大限制 ,在Linux上一般为1024,不过可以通过修改宏定义甚至重新编译内核的方式提升这一限制。 二、poll select()和poll()将就绪的文件描述符告诉进程后, 如果进程没有对其进行IO操作 ,那么 下次调用select()和poll()的时候将再次报告这些文件描述符 ,所以它们一般不会丢失就绪的消息,这种方式称为 水平触发 (Level Triggered)。 三、epoll 水平触发 和 边缘触发 ( Edge Triggered,只告诉进程哪些文件描述符刚刚变为就绪状态, 它只说一遍 ,如果我们没有采取行动,那么它将不会再次告知,这种方式称为边缘触发 ),理论上边缘触发的性能要更高一些,但是代码实现相当复杂。 , 而且当我们调用epoll_wait()获得就绪文件描述符时,返回的不是实际的描述符,而是一个代表就绪描述符数量的值, 你只需要去epoll指定的一个数组中依次取得相应数量的文件描述符即可,这里也使用了内存映射(mmap)技术

如何提高服务器并发处理能力

匿名 (未验证) 提交于 2019-12-03 00:22:01
什么是服务器并发处理能力 一台服务器在单位时间里能处理的请求越多,服务器的能力越高,也就是服务器并发处理能力越强 有什么方法衡量服务器并发处理能力 1. 吞吐率 吞吐率,单位时间里服务器处理的最大请求数,单位req/s 从服务器角度,实际并发用户数的可以理解为服务器当前维护的代表不同用户的文件描述符总数,也就是并发连接数。服务器一般会限制同时服务的最多用户数,比如apache的MaxClents参数。 这里再深入一下,对于服务器来说,服务器希望支持高吞吐率,对于用户来说,用户只希望等待最少的时间,显然,双方不能满足,所以双方利益的平衡点,就是我们希望的最大并发用户数。 2. 压力测试 有一个原理一定要先搞清楚,假如100个用户同时向服务器分别进行10个请求,与1个用户向服务器连续进行1000次请求,对服务器的压力是一样吗?实际上是不一样的,因对每一个用户,连续发送请求实际上是指发送一个请求并接收到响应数据后再发送下一个请求。这样对于1个用户向服务器连续进行1000次请求, 任何时刻服务器的网卡接收缓冲区中只有1个请求,而对于100个用户同时向服务器分别进行10个请求,服务器的网卡接收缓冲区最多有100个等待处理的请求,显然这时的服务器压力更大。 压力测试前提考虑的条件 并发用户数: 指在某一时刻同时向服务器发送请求的用户总数(HttpWatch) 总请求数 请求资源描述

高级IO:五种IO模型

匿名 (未验证) 提交于 2019-12-03 00:04:02
五种IO模型: 一.在总结五种IO模型之前我们了解一下什么是IO??? I表示input,O表示output,合在一起就是IO―表示输入输出设备;每个设备都有一个专用的IO地址,用来处理自己的输入输出信息; 需要注意:IO地址绝对不能有重复,如果两个IO地址有冲突则会造成系统硬件不能正常工作; 二. IO模型: 对于一次IO访问(以read举例),数据会先被拷贝到操作系统内核的缓冲区中, 然后才会从操作系统内核的缓冲区拷贝到应用程序的地址空间。 所以说,当一个read操作发生时,它会经历两个阶段: (1) 等待数据准备 (2)将数据从内核拷贝到进程中 在网络编程环境中,一次IO操作主要包括两个部分: 等数据准备 拷贝数据 所以如果想要提高IO效率,就应该想办法让等的比重减少。 Linux下常见五种IO模型分类: 三.五种IO模型及基本概念: 1.阻塞IO: 在内核将数据准备好之前, 系统调用会一直等,所有的套接字, 默认都是阻塞方式; 具体的过程: (1)当用户进程调用了recvfrom这个系统调用,kernel就开始了IO的第一个阶段: 准备数据(对于网络IO来说,很多时候数据在一开始还没有到达;比如,还没有收到一个完整的UDP包。这个时候kernel就要等待足够的数据到来);这个过程需要等待,也就是说数据被拷贝到操作系统内核的缓冲区中是需要一个过程的;而在用户进程这边

网络

匿名 (未验证) 提交于 2019-12-02 23:57:01
网络适配器 接收到数据后(如果目的地址不正确会丢弃),经过 I/O 总线、内存总线,复制到 内存 (通常是通过 DMA 传送),并触发 硬中断 来通知 CPU,CPU 会更新硬件寄存器状态(表示数据已经读好了),然后发送软中断信号。 软中断 处理程序(ksoftirqd 线程)为该包分配内核中的数据结构 sk_buff ,并把包复制到 sk_buff 缓冲区 中。内核从缓冲区取出来,通过网络协议栈 逐层处理包 。传输层里取出 TCP 或 UDP 头后,根据 { 源 IP,源端口,目的 IP,目的端口 } 找出 对应的 socket ,把数据复制到 socket 的 接收队列缓冲区 中。应用程序通过 socket 接口 获取到该数据。 应用程序通过 socket 系统调用 陷入内核,内核把数据放到 socket 的 发送缓冲区 。网络协议栈取出数据后,按照 TCP/IP 逐层处理。比如传输层、网络层,分别增加 TCP 头、IP 头,执行路由查找 下一跳 IP ,并按照 MTU 大小进行 分片 。 分片后的网络包,送到网络接口层,进行物理地址寻址,以找到下一跳的 MAC 地址 。然后放到发包队列,通过 软中断 ֪ͨ 驱动程序 。 最后,驱动程序通过 DMA ,从发包队列中取出网络帧,并通过 网卡 把它发送出去。 所谓连接,就是两端 数据结构 是否对得上。符合 TCP 协议规则