指针数组作为参数在函数间传参_结构体数组指针做函数参数

指针数组作为参数在函数间传参_结构体数组指针做函数参数2023秋招大厂经典面试题及答案整理归纳(61-80)校招必看!61. 两个长度不超过80的字符串,串中包括大写、小写和空 格字符,去掉空格字符并忽略大小写后判断两个字符串是否 相等。输入描述:第一行输入的是测试数据的组数n,每组测试数据占两行,第一行是第一个 字符申S1,第

2023秋招大厂经典面试题及答案整理归纳(61-80)校招必看!   61. 两个长度不超过80的字符串,串中包括大写、小写和空 格字符,去掉空格字符并忽略大小写后判断两个字符串是否 相等。   输入描述:第一行输入的是测试数据的组数n,每组测试数据占两行,第一行是第一个 字符申S1,第二行是第二个字符申S2o输出描述:如果两个字符串相等,则输出YES,否则输出旳。样例输入:   本題主要用到字符串处理函数   62. 归并排序的实现.   归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer )策略(分治法将问题分(divide)成一些小的问题然后递归求解> 而治(conquer)的阶段则将分的阶段得到的各答案〃修补〃在一起,即分而治之)。 归并排序中,我们会先找到一个数组的中间下标mid,然后以这个mid为中心,对两边 分别进行排序,之后我们再根据两边已拝好序的子数组,重新进行值大小分配。 我们就以下面的数组为例:
指针数组作为参数在函数间传参_结构体数组指针做函数参数
指针数组作为参数在函数间传参_结构体数组指针做函数参数   (1)mid等于数组最大下标/ 2 = 3,于是我们以下标3 (值为7)为中心,分别排序0~3和4曾的数字。(2 )此时两边的数组还可以创建分支:
指针数组作为参数在函数间传参_结构体数组指针做函数参数
指针数组作为参数在函数间传参_结构体数组指针做函数参数   (4)可以看到,此时我们已经无法继续创建分支了,因为数组数量为1时是没有必要 进行排序的,这时我们可以开始进行对冬一个小的数组进行排序并且合并:   
指针数组作为参数在函数间传参_结构体数组指针做函数参数
指针数组作为参数在函数间传参_结构体数组指针做函数参数   
指针数组作为参数在函数间传参_结构体数组指针做函数参数
指针数组作为参数在函数间传参_结构体数组指针做函数参数   代码如下:   63. 二叉树先序遍历(递归与非递归)及C语言实现.   二叉树先序遍历的实现思想是:访问根节点;访问当前节点的左子树;若当前节点无左子树,则访问当前节点的右子树;
指针数组作为参数在函数间传参_结构体数组指针做函数参数
指针数组作为参数在函数间传参_结构体数组指针做函数参数   以图1为例,采用先序遍历的思想遍历该二叉树的过程为: 访问该二叉树的根节点,找到1;访问节点1的左子树,找到节点2;访问节点2的左子树,找到节点4;由于访问节点4左子树失败,且也没有右子树,因此以节点4为根节点的子树遍历完 成。但节点2还没有遍历其右子树,因此现在开始遍历,即访问节点5;由于节点5无左右子树,因此节点5遍历完成,并且由此以节点2为根节点的子树 也遍历完成。现在回到节点1 ,并开始遍历该节点的右子树,即访问节点3;访问节点3左子树,找到节点6;由于节点6无左右子树,因此节点6遍历完成,回到节点3并遍历其右子树,找到 节点节点7无左右子树,因此以节点3为根节点的子树遍历完成,同时回归节点1。由于 节点1的左右子树全部遍历完成,因此整个二叉树遍历完成;因此,图1中二叉树采用先序遍历得到的序列为:1 2 4 5 3 6 7 逢归城:二叉树的先序遍历采用的是逢归的思想,因此可以逢归实现。   64. 将“引用”作为函数参数有哪些特点?   1) 传递引用给函数与传递指针的效果是一样的。这时,被调函数的形参就成为原来主调 函数中的实参变里或对象的一个别名来使用,所以在被调函数中对形参变里的操作就是 对相应的目标对象(在主调函数中)的操作。2) 使用引用传递函数的参数,在内存中并没有产生实参的副本,它是直接对实参操作量 传递函数当发生函数调用时,需要给形参分配存储单是实参变里的副本;如果传递的 是对象,还将调用拷贝构造函数。因此,当参数传递的数据较大时,用引用比用一般变量 传递参数的效率和所占空间都好。(3)使用指针作为函数的参数虽然也能达到与使用引 用的效果,但是,在被调函数中同样要给形参分配存储单,且需要重复使用指针变里名 的形式进行运算,这很容易产生错误且程序的阅读性较差;另一方面,在主调函数的调用 点处,必须用变里的地址作为实参。而引用更容易使用,更清晰。52. 顺序栈的表示和实现顺序栈,即栈的顺序存储结构是利用一组池址连续的存储单依次存放自栈底到栈顶的 数据素,同时附设指针top指示栈顶素在顺序栈中的位置。通常的习惯做法以top=0 表示空栈。一般来说,在初始化设空栈旺不应限定栈的最大容量。一个较合理的做法: 先为栈分配一个基本容量,然后在应用近程中,当栈的空间不足在进行扩展。   65. 请描述索引的特征?   索引有两个特征,即唯一性索引和复合索引。   唯一性索引保证在索引列中的全部数据是唯一的,不会包含冗余数据。如果表中已经 有一个主键约束或者唯一性键约束,那么当创建表或者修改表时,SQL Server自动创 建一个唯一性索引。然而,如果必须保证唯一性,那么应该创建主键约束或者唯一性键 约束,而不是创建一个唯一性索引。当创建唯一性索引时,应该认真考虑这些规则: 当在表中创建主键约束或者唯一性键约束时,SQL Server g动创建一个唯一性索引; 如果表中已经包含有数据,那么当创建索引时,SQL Server检查表中已有数据的冗余 性;每当使用插入语句插入数据或者使用修改语句修改数据时,SQL Server检查数据 的冗余性:如果有冗余值,那么SQL Server 消该语句的执行,并且返回一个错误消 息;确保表中的每一行数据都有一个唯一值,这样可以确保每一个实体都可以唯一确认; 只能在可以保证实体完整性的列上创建唯一性索引,例如,不能在人事表中的姓名列 上创建唯一性索引,因为人们可以有相同的姓名。   复合索引就是一个索引创建在两个列或者多个列上。在搜索时,当两个或者多个列作 为一个关键值时,最好在这些列上创建复合索引。当创建复合索引时,应该考虑这些规 则:最多可以把16个列合并成一个单独的复合索引,构成复合索引的列的总长度不能 起过9。。字节,也就是说复合列的长度不能太长;在复合索引中,所有的列必须来自同 —个表中,不能跨表建立复合列;在复合索引中,列的排列顺序是非常重要的,因此 要认真排列列的顺序,原则上,应该首先定义最唯一的列,例如在(C0L1, C0L2)上的 索引与在(C0L2, C0L1)上的索引是不相同的,因为两个索引的列的顺序不同;为了 使查询优化器使用复合索引,查询语句中的雌职子句必须参考复合索引中第一个列; 当表中有多个关键列时,复合索引是非常有用的;使用复合索引可以提高查询性能,减 少在一个表中所创建的索引数量。   66. 如何理解聚簇索引和非聚簇索引的的体系结构?   聚篠索引的体系结构索引的结构类似于树状结构,树的顶部将为叶级,树的其它部分称为非叶级,树的根部 在非叶级中。同样,在聚簇索引中,聚簸索引的叶级和非叶级构成了一个树状结构, 索引的最低级是叶级。在聚簇索引中,表中的数据所在的数据页是叶级,在叶级之上的 索引页是非叶级,索引数据所在的索引页是非叶级。在聚簇索引中,数据值的顺序总 是按照升序排列。   应该在表中经常搜索的列或者按照顺序访问的列上创建聚簇索引。当创建聚簇索引时, 应该考虑这些因素:每一个表只能有一个聚簇索引,因为表中数据的物理顺序只能有 —个;表中行的物理顺序和索引中行的物里顺序是相同的,在创建任何非聚簇索引之前 创建聚簇索引,这是因为聚簇索引改变了表中行的物理顺序,数据行按照一定的顺序 排列,并且自动维护这个顺序;关键值的唯一性要么使用UNIQUE关键字明确维护,要 么由一个内部的唯一标识符明确维护,这些唯一性标识符是系统自己使用的,用户不 能访问;聚簇索引的平均大小大约是数据表的百分之五,但是,实际的聚簇索引的大小 常常根据索引列的大小变化而变化;在索引的创建过程中,SQL Server 1^时使用当前 数据库的磁盘空间,当创建聚簇索引时,需要1.2倍的表空间的大小,因此,一定要保 证有足够的空间来创建聚簇索引。   当系统访问表中的数据时,首先确定在相应的列上是否存在有索引和该索引是否对要 检索的数据有意义。如果索引存在并且该索引非常有意义,那么系统使用该索引访问 表中的记录。系统从索引开始浏览到数据,索引浏览则从树状索引的根部开始。从根部 幵始,搜索值与每一个关键值相比较,确定搜索值是否大于或者等于关键值。这一步 重复进行,直到碰上一个比搜索值大的关键值,或者该搜索值大于或者等于索引页上所 有的关键值为止。非聚篠索引的体系结构   非聚簇索引的结构也是树状结构,与聚簸索引的结构非常类似,但是也有明显的不同。 在非聚簇索引中,叶级仅包含关键值,而没有包含数据行。非聚簇索引表示行的逻辑顺 序。非聚簇索引有两种体系结构:一种体系结构是在没有聚簇索引的表上创建非聚簇 索引,另一种体系结构是在有聚簇索引的表上创建非聚簇索引。如果一个数据表中没有聚簇索引,那么这个数据表也称为数据堆。当非聚簇索引在数 据堆的顶部创建时,系统使用索引页中的行标识符指向数据页中的记录。行标识符存 储了数据所在位置的信息。数据堆是通迂使用索引分配图<M)页来维护的。L娜页 包含了数据堆所在簇的存储信息。在系统表sysindexes中,有一个指针指向了与数据 堆相关的第一个L娜页。系统使用L娜页在数据堆中浏览和寻找可以插入新的记录行的 空间。这些数据页和在这些数据页中的记录没有任何的顺序并且也没有链接在一起。 在这些数据页之间的唯一的连接是L娜中记录的顺序。当在数据堆上创建了非聚簇索引 时,叶级中包含了指向数据页的行标识符。行标识符指定记录行的逻辑顺序,由文件 ID、页号和行ID组成。这些行的标识符维持唯一性。非聚簇索引的叶级页的顺序不同 于表中数据的物理顺序。这些关键值在叶级中以升序维持。   当非聚簇索引创建在有聚簇索引的表上的时候,系统使用索引页中的指向聚簇索引的聚 簇键。聚簇键存储了数据的位置信息。如果某一个表有聚簇索引,那么非聚簇索引的 叶级包含了映射到聚簇键的聚簇键值,而不是映射到物理的行标识符。当系统访问有非 聚簇索引的表中数据时,并且这种非聚熊索引创建在聚簇索引上,那么它首先从非聚 簇索引来找到指向聚簇索引的指针,然后通过使用聚簇索引来找到数据。当需要以多种方式检索数据时,非聚簇素引是非常有用的。当创建非聚簇索引时,要考 虑这些情况:在缺省情况下,所创建的索引是非聚簇索引;在每一个表上面,可以创建 不多于249个非聚簇索引,而聚簇索引最多只能有一个。   系统如何访问表中的数据—般地,系统访问数据库中的数据,可以使用两种方法:表扫描和索引查找。第一种 方法是表扫描,就是指系统将指针放置在该表的表头数据所在的数据页上,然后按照 数据页的排列顺序,一页一页地从前向后扫描该表数据所占有的全部数据页,直至扫描 完表中的全部记录。在扫描时,如果找到符合查询条件的记录,那么就将这条记录挑 选出来。最后,将全部挑选出来符合查询语句条件的记录显示出来。第二种方法是使用 索引查找。索引是一种树状结构,其中有储了关键字和指向包含关键字所在记录的数 据页的指针。当使用索引查找时,系统沿着索引的树状结构,根据索引中关键字和指针, 找到符合查询条件的的记录。最后,将全部查找到的符合查询语句条件的记录显示出 来。   在SQL Server中,当访问数据库中的数据时,由SQL Server确定该表中是否有索引存 在。如果没有索引,那么SQL Server使用表扫描的方法访问数据库中的数据。查询处 理器根据分布的统计信息生成该查询语句的优化执行规划,以提高访问数据的效率为目 标,确定是使用表扫描还是使用索引。   67. C和C++有什么不同?   从机制上:C是面向过程的(但C也可以编与面向对象的程序)。c+4是面向对象的,提供 了类。但是,c卄编写面向对象的程序比c容易。   从适用的方向:c适合要求代码体积小的,效率高的场合,如嵌入式;C-适合更上层的复 杂的;linux核心大部分是c写的,因为它是系统软件,效率要求极高从名称上也可以看出,c卄比c 多了 +说明crH是c的超集;那为什么不叫c+而叫c+磯,是因为c卄比C来说扩充的东西太多 了,所以就在c后面放上两个+;于是就成了 C++。   C语言是结构化编程语言,CH是面向对象编程语言。LUPA开源社区} n*r2C/J.!8fCi侧重于对象而不是过程,侧重于类的设计而不是逻辑设计.   68. 头文件的作用时什么?   一、 通过头文件来调用库功能。在很多场含,源代码不便(或不准)向用户公布,只要向用 户提供头文件和二进制的摩即可。用户只需要按照头文件中的接口声明来调用库功能而 不必关心接口怎么实现的。编译器中提取相应的代码。   二、 头文件能加强类型安全检查。如果某个接口被实现或被使用时,其方式与头文件中 的声译器就会指出错误简单的规则能大大碱轻程序员调试、改错的负担。   69. memcpy函数实现.   memcpy函数作用:将由灯c指向地址为起始地址的连续n个字节的数据复制到以de”指向地址为起始地 址的空间内,函数返回一个指向dest的指针   舫嫩:1- src和de st所指内存区域不能重囊2. 与strcpy相比,memcpy遇到并不会结束,而是一定会拷贝完n个字节3. memcpy可以拷贝任何数据类型的对象,可以指定拷贝的数据长度4. 如果dest本身就有数据,执行memcpy ()后会覆盖原有的数据5. de”和src都不一定时数组,任意的可读写的空间均可6. 如果要追加数据,则每次执行memcpy后,要将目标数组地址増加到所要追加数据的 地址   弟见代码:   70. 寻找二叉树中两个节点的最近公共祖先节点   —、该二叉树为搜索二叉树搜索二叉树的特点:任意一个节点的左子树的所有节点值都比该节点的值小,其右子树的所有节点值都比该 节点的值大。解决该问题方法:从树的根节点开始和两个节点作比较,殳戚当前节点的值比两个节点的值都大,则这两 个节点的最近公共祖先节点一定在该节点的左子树中,则下一步遍历当前节点的左子 树;如果当前节点的值比两个节点的值都小,则这两个节点的最近公共祖先节点一定在该节 点的右子树中,下一步遍历当前节点的右子树;这样直到找到第一个值是两个输入节点 之间的值的节点,该节点就是两个节点的最近公共祖先节点。如图:
指针数组作为参数在函数间传参_结构体数组指针做函数参数
指针数组作为参数在函数间传参_结构体数组指针做函数参数   二、该二叉树为一般二叉树,有二叉树节点中包含指向父节点的指针   首先给出nodel的父节点nodel-^arent,然后将nodel的所有父节点依次和 node2->pazent作比较,如果发现两个节点相等,则该节点就是最近公共祖先,直接将 其返回。如果没找到相等节点,则将node2的所有父节点依次和 nodel~>_parent->_paxent 作比较 直到   
指针数组作为参数在函数间传参_结构体数组指针做函数参数
指针数组作为参数在函数间传参_结构体数组指针做函数参数   代码如下:   71. 死锁产生的条件,以及如何避免死锁,银行家算法,产生死锁后如何解决?   产生死锁的四个必要条件(互请不循):(1) 互斥条件:一个资源每次只能被一个进程使用。(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。(4) 循环等待条件:若干进程之间形成一种头尾相接的【循环等待资源】关系。 避免死锁:   (1) .按同一顺序访问对象。(注:避免出现循环)   (2) .避免事务中的用户交互。(注:减少持有资源的时间,较少锁竟争)   (3) .保持事务简短并处于一个批处理中。(注:同(2),减少持有资源的时间)   (4) .使用较低的隔离级别。(注:使用较低的隔离级别(例如已提交读)比使用较高的 隔离级别(例如可序列化)持有共享锁的时间更短,减少锁竟争)   (5) .使用基于行版本控制的隔离级别:   银行家算法   银行家算法是一个避免死锁的著名算法,它是以银行借贷系统的分配策略为基础,判断 并保证系统的安全运行。   总之:个进程申请使用资源的时候,银行家算法通过【先试探分配给该进程资源】,然 后【通过安全性算法判断分配后的系统是否处于安全状态L若不安全则试探分配作废, 让该进程继续等待。   当一进程提出资源申请时,银行家算法执行下列步骤以决定是否向其分配资源:   1) 检查该进程所需要的资源是否已超过它所宣布的最大值。   2) 检查系统当前是否有足够资源满足该进程的请求。   3) 系统试探着将资源分配给该进程,得到一个新状态。   4) 执行安全性算法,若该新状态是安全的,则分配完成;若新状态是不安全的,则恢 复原状态,阻塞该进程。   假设资源P1申请资源,银行家算法先试探的分配给它(当然先要看看当前资源池中的 资源数量够不够),【若申请的资源数量小于等于Available,然后接着判断分配给Pl 后剩余的资源,能不能使进程队列的某个进程执行完毕】,【若没有进程可执行完毕, 则系统处于不安全状态】(即此时没有f进程能够完成并释放资源,随时间推移,系 统终将处于死锁状态)。   若有进程可执行完毕,则假设回收已分配给它的资源(剩余资源数量増加),把这个进 程标记为可完成,并继续判断队列中的其它进程,若所有进程都可执行完毕,则系统处 于安全状态,并根据可完成进程的分配顺序生成安全序列(如{P0, P3, P2, P1}表示将 申请后的剩余资源Work先分配给P0 -〉回收(Work+已分配给P0的A0=Work)- >分配 给P3 – >回收(Work+A3=Work)- >分配給P2 – > 满足所有进程)。   72.在KMP算法中,已知模式串为ADABCADADA,请写出模 式串的next数组值.   ’前缀’指除了最后一个字符以外,一个字符串的全部头部组合;’后缀’指除了第一个字 符以外,一个字符串的全部尾部组合。next数组值就是’前缀’和’后缀’的最长的共有 素的长度。   首先求最大相同前缀后缀长度。W的前缀和后缀都为空集,没有共有素,共有素 长度为O;AD ‘的 前缀为[A],后缀为[D],没有共有素,共芍素长度为0/ ADA ‘的前缀为[A,.W],后缀 为[DA, A],共有素为A,长度为1;’ ADAB ‘的前缀为[出.W, ADA],后缀为[DAB, AB, B], 共有素长度为。;以此类推,最大公共素长度为:   0,1,0,0,1, 23,2。   然后将最长相同前缀后缀长度值右移一位,并将next [0]初值赋为-1,得到的next数组: -1,0,0,1,0,0,1, 2,3,2。   在某些语言中,数组不是从。开始索引的,而是从1开始索引,只需要将next数组中每个 值加L得到   0,1,1, 2,1,1, 2, 3,43。   所以结果为 0,1,1, 2,1,1, 2, 3,43   73. 寻找两个有序数组的中位数   74. C卄实现线程安全的单例模式   懒汉模式:   75. 数组中有三个数字出现超过1/4,求这三个数字?   76. l-2n的数存储在空间为n的数组中,找岀出现两次的数 字,时间复杂度O (n),空间复杂度O (1)   77. 长度为1的线段,随机在其上选择两点,将线段分为三段,问这3段能组成一个三角形的概率是多少?   可行域是x+y+z=l, 0<X, y, Z<1显然,可行域与我的博客一条长度为1依线段,随机煎两刀,求有一根大于。. 5的概率 问题一样。要令三段成为一个三角形,必须满足x+y>z, x+z>y, y+z>xI x_y I <z, I x-z I <y, | y-z I <x又 x+y+z=l,当 x+y=z 时,有 z=0. 5 z=0.5z=0. 5,因此当 x, y, z 中有一个大于 0. 5 时, 就无法成立一个三角形。当x-y=z时,将x-y=z代入x+y+z=l,可得x=0. 5。因此当x, y, z中有一个大于0. 5时, 就无法成立一个三角形。因此解空间刚好与一条长度为1的线段,随机煎两刀,求有一根大于0.5的概率相反。 而一条长度为1的线段,随机萸两刀,求有一根大于0.5的概率的概率为0. 75。因此这3 段能组成一个三角形的概率是多少是1-0. 75=0. 25。   78. 智能指针的实现原理?   智能指针的基本原理就是将指针通过对象去管理,delete的操作利用析构函数执行, 而析构函数的调用是根据这个对象的作用域来确定的,离开了作用域,析构函数被调用。 delete的操作也将被执行。   79. 请解释什么是C1OK问题,后来是怎么解决的?   1. C10K问题   互联网还不够普及,用户也不多。一台服务器同时在线100个用户估计在当时已经算是 大型应用了。所以并不存在什么C10K的谁題。互联网的爆发期应该是在ww网站,浏 览器,雅虎出现后。最早的互联网称之为Webl.O,互联网大部分的使用场景是下载一 个Html页面,用户在浏览器中查看网页上的信息。这个时期也不存在C10K问题。   Web2.0时代到来后就不同了,一方面是普及率大大提高了,用户群体几何倍増长。另 一方面是互联网不再是单纯的浏览万维网网页,逐渐开始进行交互,而且应用程序的逻 辑也变的更复杂,从简单的表单提交,到即时通信和在线实时互动。C10K的问题才体 现出来了。每一个用户都必须与服务署保持KT连接才能进行实时的数据交互。 Facebook这样的网站同一时间的并发TCP连接可能会过亿。   腾讯sigusoft也是有C10K问题的,只不过他们是用了 UDP这种原始的包交换协议来实现的, 绕开了这个难题。当然过程肯定是痛苦的。如果当时有epoll技术,他们肯定会用TCPo 后来的手机sigusoft,都采用TCP协议。   这时候问题就来了,最初的服务器都是基于进程/线程模型的,新到来一个”P连接, 就需要分配1个进程(或者线程)。而进程又是操作系统最昂贵的资源,一台机器无法 创建很多进程。如果是C10K就要创建1万个进程,那么操作系统是无法承受的。如果 是采用分布式系统,维持1亿用户在线需要10万台服务器,成本巨大,也只有Facebook,   Google,雅虎才有财力购买如此多的服务器。这就是C10K问题的本质。   实际上当时也有异步模式,如:select/po:l模型,这些技术都有一定的缺点,如selelct 最大不能超过1024, poll没有限制,但毎次收到数据需要遍历每一个连接查看哪个连 接有数据请求。   2. 解决方案   解决这一问题,主要思路有两个:   —个是对于每个连接处理分配一个独立的进程/线程:   另一个思路是用同一进程/线程来同时处理若干连接。   每个进程/线程同时处理多个连接   1. 传统思路   最简单的方法是循环挨个处理各个连接,毎个连接对应一个socket,当所有socket都 有数据的时候,这种方法是可行的。   但是当应用读职某个socket的文件数据不ready的时候,整个应用会阻塞在这里等 待该文件句柄,即使别的文件句柄ready,也无法往下处理。   思路:直接循环处理多个连接。   问题:任一文件句柄的不成功会阻塞住整个应用。   2. select   要解决上面阻塞的问题,思路很简单,如果我在读职文件句柄之前,先查下它的状态, ready 了就进行处理,不ready就不进行处理,这不就解决了这个问题了嘛? 于是有了 select方案。用一个fd_set结构体来告诉内核同时监控多个文件句柄,当 其中有文件句柄的状态发生指定变化(例如某句柄由不可用变为可用)或超时,则调用 返回。之后应用可以使用FD.ISSET来逐个查看是哪个文件句柄的状态发生了变化。   这样做,小规模的连接问题不大,但当蟻数很多(文件句柄个数很多)的时候,逐个 检查状态就很慢了。因此,select往往存在管理的句柄上限(FILSETSIZE)。同时, 在使用上,因为只有一个字段记录和发生事件,每次调用之前要重新初始化fd_set 结构体。   int select(int nfds, fd_set *readfds, fd_set *wxitefds, fd_set *exceptfds, struct timeval *timeout);   思路:有连接请求抵达了再检查处理。   问题:句柄上限+重复初始化+逐个排查防有文件句柄状态效率不高。   3. poll   poll主要解决select的前两个问题:通过一个pollfd数组向内核传递需要的 事件消除文件句柄丄限,同时使用不同字段分别标注事件和发生事件,未避免重复 初始化。   int poll (struct pollfd *fds, nfds__t nfds, int timeout);   思路:设计新的数据结构提供使用效函。   问题:逐个排查所有文件句柄状态效率不高。   4. epoll   既然逐个排查所有文件句柄状态效率不高,很自然的,如果调用返回的时候只给应用提 供发生了状态变化(很可能是数据ready)的文件句柄,进行排查的效率不就高多了么。   epoll采用了这种设计,适用于大规模的应用场景。   实验表明,当文件句柄数目超过10之后,epoll性能将优于select和poll;当文 件句柄数目达到10K的时候,epoll已经超过select和poll两个数量级。   int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);   思路:只返回状态变化的文件句柄。   问题:依赖特定平台(Linux)。   因为Linux是互联网企业中使用率最高的操作系统,Epoll就成为C10K killer、高并 发、高性能、异步非阻塞这些技术的代名词了。   5. libevent   由于epoll, kqueue, IOCP每个接口都有白己的特点,程序移植非常困难,于是需要对 这些接口进行封装,以让它们易于使用和移植,其中libevent库就是其中之一。跨平 台,封装底层平台的调用,提供统一的AH,但底层在不同平台上自动选择合适的调用。 按照libevent的官方网站,libevent库提供了以下功能:当一个文件描述符的特定事 件(如可读,可写或出错)发生了,或一个定时事件发生了,libevent就会自动执行 用户指定的回调函数,来处理事件。目前,libevent已支持以下接口/dev/poll, kqueue, event ports, select, poll和epollo Libevent的内部事件机制完全是基于所使用 的接口的。因此libevent非常容易移植,也使它的扩展性非常容易。目前,libevent 已在以下操作系统中编译通过:Linux, BSD, Mac OS X, Solaris和Windows。   80. 使用“反向代理服务器”的优点是什么?   CD提高访问速度   由于目标主机返回的数据会存在代理服务器的硬盘中,因此下一次客户再访问相同的站 点数据时,会直接从代理服务器的硬盘中读取,起到了緩存的作用,尤其对于热门站点 能明显提高请求速度。   (2)防火墙作用   由于所有的客户机请求都必须通过代理服务器访问远程站点,因此可在代理服务器上设 限,过滤某些不安全信息。   <3)通过代理服务器访问不能访问的目标站点   互联网上有许多开发的代理服务器,客户机可访问受限时,可通过不受限的代理服务器 访问目标站点,通俗说,我们使用的翻墙浏览器就是利用了代理服务器,可直接访问外网。   秋招大厂经典面试题及答案整理不断更新中,感兴趣且正在学习的同学可以点个;狮会不断更新文章连载,有问题或者见解可以评论区讨论。

2024最新激活全家桶教程,稳定运行到2099年,请移步至置顶文章:https://sigusoft.com/99576.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。 文章由激活谷谷主-小谷整理,转载请注明出处:https://sigusoft.com/38660.html

(0)
上一篇 2024年 9月 8日 下午3:12
下一篇 2024年 9月 8日 下午3:16

相关推荐

关注微信