男朋友问我为什么爱他他会问我这个?我的两个好友都这么问我。进去以后得从后台关闭。直接按返回退不出来。

iPhone 6plus怎么开启微博后台运行?我的微博每次看一会,只要打开其他的app,再回来用微_百度知道
iPhone 6plus怎么开启微博后台运行?我的微博每次看一会,只要打开其他的app,再回来用微
iPhone 6plus怎么开启微博后台运行?我的微博每次看一会,只要打开其他的app,再回来用微博的时候它就重新开启一遍,之前看的微博记录就没了,又得重新找,怎么办?
我有更好的答案
1、苹果6plus后台应用程序刷新,开启需要进入到设置里面开启。2、点击设置——通用——后台应用程序刷新,点击进入就可以开启自动刷新的功能。关闭后台:iPhone6任意系统界面,都可以通过双击底部的“Home键”打开iOS8多任务管理界面,效果图如下:双击iPhone6的Home键会,界面上会显示所有此前已经打开的iOS8应用,并且可以通过左右滑动,显示更多已经打开的应用。只需要拖动需要关闭的应用程序略缩图,然后向顶部滑动,等待其消失后,就成功关闭了此应用,如果需要关闭多个应用,同样都是推动图标,网上移动,直到消失即可。
采纳率:100%
按一下home键退出微博,之后再按两下home键进去后台,直接点击就能看了,你试试
我每次都是这样进去的,可是微博还是会重启
你进客户端,点设置,里面有一个通知设置,下拉到最后,点获取新消息,进去选择关闭,这样就不会自动刷新了,你试试行不行
好,我试试
本回答被网友采纳
为您推荐:
其他类似问题
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。为什么我手机的程序在后台运行,不到两分钟就会自己关闭?我是小米5_百度知道
为什么我手机的程序在后台运行,不到两分钟就会自己关闭?我是小米5
我有更好的答案
到 设置 电量和性能 神隐模式 应用配置 找到那个软件 再点击 无限制
如若无效请到 设置 我的设备 全部参数 连续点击 MIUI版本五次然后到 设置 更多设置 开发者选项 拉到最低下点击
系统内存优化级别 禁用 即可
采纳率:62%
为您推荐:
其他类似问题
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。这两天网上热议的奔驰失控事件想必大家都有所耳闻,具体经过车行哥在这里就不多讲了,网上一搜一大把。总之目前稍微有点汽车专业知识的人基本都质疑车主的说辞,讲道理,车行哥也认同这些观点。找了个总结比较简明全面的博主的博文吧:
不过事件目前还未有奔驰or警方的官方定论,所以车行哥也暂时持保留态度。
但是,车行哥觉得这个事件能一下子火起来,确实也显现出很多社会现象和汽车产业发展的问题。下面车行哥就从中体现出来的与汽车行业强相关的两个问题点跟大家讨论下。
▍问题1:我弱我有理,顾客是上帝,商家心里MMP
也不知道是哪一年开始,似乎“维权”就成了热门词,这在汽车界也不例外。反正车子出了问题,经销商给不出满意的解决方案和态度的时候,就有越来越多的车主选择了“维权”这条道路。
虽然这种趋势的形成跟车行哥的媒体同行们脱不开关系(毕竟要生存嘛),车行哥之前也跟过这类新闻事件,但是车行哥对于这类事件的看法一直跟主流观点不太一样。因为绝大多数这类事件的症结其实就是沟通不畅。
首先,消费者相较于厂商来说,确实是弱势群体,这点毋庸置疑。但是时下不管任何新闻事件的评论里有充斥着“我弱我有理”这种奇葩逻辑,车行哥是绝对不认同的。
因为这种“弱者心理”加上对汽车知识的匮乏和社会固有的对商人的信任缺失,导致了一旦出了问题,厂商方面跟这类消费者沟通起来将会非常费劲。而个别态度有问题的厂商更是在其中起到了火上浇油的作用。
其次就是“顾客是上帝,你必须按我满意的要求来处理”这种观点,车行哥也是不认同的。所有厂家(包括非汽车产品)的售后服务处理都是有规范的,这个规范充分考虑国家相关法律和企业运营承受能力基础上,尽可能为消费者提供满意的服务而建立的,而非像不少消费者认为的那样“就是想打发我”(虽然也有个别厂商做得不到位,但是真心是少数了)。
最后,车行哥还得就这类事件同情下经销商。讲道理,他们的专业度和处理权限真心非常有限,所有技术类操作指导都是厂家下发的,基本就是处于“知其然不知其所以然”的状态。但是他们却被迫成为车主和厂家之间沟通的桥梁,两面都中枪,却还两面都不讨好。车行哥甚至见过不少经销商为了店面声誉自掏腰包来安抚车主,可是这个锅是厂家甩过来的呀!
车行哥就是想对广大车主们说句,如果真遇到问题,直接找厂家要说法,或者找质检总局、找中消协协助解决,别去为难经销商了。他们其实比你更无奈(没有能力和权限去解决),也更着急(你只是亏了一台车,他们可能就卖不出去车了)。
▍问题2:自动驾驶?车载互联?智能网联汽车到底靠不靠谱?
主观上来说,车行哥因为对机械的迷恋,更喜欢老到连ECU和电喷都没有的车型。但是客观来讲,汽车必然是越先进的越可靠。
在一定程度深入了解了相关专业知识前,人们对于新技术几乎都会抱有恐惧心理,从而产生质疑和不接受。原因很简单,因为不了解,所以不直观,自然就不信任。
当你问一个对电子设备、编程一窍不通的人,电脑和老司机操作机器哪个靠谱时,他绝对会说老司机靠谱。因为老司机和他们自己一样,都是通过眼手配合来开车,所以很直观,感觉很靠谱。而对于电脑操作机器是什么原理他们完全没概念,只能通过类似经验,比如平时用PC和手机来揣测,感觉经常出bug、死机,于是就觉得电脑不靠谱。
车行哥觉得,这种因为不了解而倾向于相信老司机的思维模式,跟相信老中医而不信现代医学简直如出一辙,都是因为无知还不好学。
这里,车行哥找了一张图,从中可以清晰看出智能网联汽车的发展趋势:
这次奔驰失控事件最开始迅速火起来,有个很重要的原因,是因为有报道误称奔驰在后台关闭了事故车辆的ACC定速巡航系统。看到这个误报,很多人一下子就炸了:我的车可以被别人从后台控制?!车行哥只能说,你们好莱坞大片看太多了吧……
要从后台直接对车辆进行操控,要发展到网联协同决策与控制阶段,对应的智能驾驶技术必须达到高度/完全自动驾驶,这种技术目前世界上还没有哪一家有,所以大家不必担心。
而对于目前很多车型都有的一些电子辅助驾驶系统,比如自适应巡航、自动紧急制动、车道保持、辅助自动泊车等系统,只要你不乱改装,理论上是不可能出BUG导致强制介入干预你的驾驶行为的。因为从设计上,这些电子系统只是起到辅助作用,很多都采用“负触发”机制,也就是启动状态并非持续运行,而是每隔很短一段时间就会退出,然后排查所有系统运行是否正常,确认后再重启。这个过程非常快,我们根本感觉不出。
除开BUG,举个极端的例子,即使是一个EMP(电磁震荡)过来,让所有车上电子设备瘫痪,那最多也就是失去动力和刹车以及转向助力。注意!这里是失去的只是助力!我们平时说的电子踏板和电子方向盘只是指的是电子助力踏板和电子助力方向盘,而踏板和方向盘始终还是与机械结构链接且可以操控的。
电子助力瘫痪后,只会造成操作阻尼变大,不会失效(油门除外,因为控制动力的除了油门还有点火)。开过没助力的老车的人应该能理解是怎样的感受。
综上,关于这次奔驰失控事件带来的恐慌以及对于智能网联汽车技术的恐惧都是缺失理性的。要相信,工程师绝对比你们想得全面,而且还有很多国家法律法规强制要求,从设计原理上,即使是有辅助驾驶系统的情况下,很多涉及到安全的系统都是可以独立运行且驾驶员具有绝对优先权的。
▍多读书少看报,多查资料少乱叫
在网络信息时代,在网上发言承担的风险确实很小,为了应对失效和信息量的需求,媒体报道的公信度也越来越低。所以,车行哥谨以此文告诫大家:多读书少看报,多查资料少乱叫。
要培养自己独立思考,求证的能力,求证后再发言,平时也要注意增加自身的知识储备,绝对没坏处。不要随意站队、起哄,更不要恶意炒作!虽然瞎BB和吹NB不上税,而且在网上换个马甲也没人认得出。但是键盘党们,你们的良心不会不安么?还是压根就没良心?
文章转载自网络,作者观点不代表本网站立场,如需处理请联系客服
月月话娱其它文章
老公不尊重我,他家人看不起我是农村人,这样的婚姻该不该继续?故事角色
男主人公:王康女主人公:张甜甜工作几年的张甜甜始终没遇到自己心中的白马王子,迫于家人压力,心想有合适的就凑合着过,婚后两个人再好好培养感情,于是通过相亲匆匆与王康结婚了。结婚不到半
相信有不少的漂亮女生们,都遇到过一些已婚男士的追求,尤其是在那些大公司里的领导,或者自己的上司;一些刚刚大学毕业的女生们,面对感情很不懂事,一旦遇到对方的温柔攻击,很容易被征服;如果你是一个正处在这种矛盾中的女生,可以试试下面的这几个方法,小编今天的分
一、帮她介绍到你公司上班!和你关系再好的女人,这几种忙不要帮,不然铁定会“出事”:帮她介绍到你公司上班!朋友之间互相介绍个工作也是很平常的事,但朋友和同事毕竟不一样,毕竟公司不是避难所,最好不要把好友介绍到自己公司上班,因为每个岗位都需要各司其责,他
在世界历史上,任何一场战争的爆发,都会催生出一些投敌的汉奸。汉奸的存在是有一定的道理,他可能受到当时的战争形势的影响,为了保命向敌人缴械投降。在中国抗日战争史上,出现了一批又一批的汉奸,而汉奸的人数也是让人觉得匪夷所思,前后达到了百万之数。那么为何抗
欢迎来到百家号,我是马勃谈历史故事的小编,今天给大家讲的是唐朝中期的理财家刘宴的故事。我们一起来看看他是怎么让漕运发展的吧!开元二十九年,陕郡太守李齐物凿砥柱为门以通漕,开其山巅为挽路烧石沃醯而凿之。逾岩险之地俾负索引舰升于安流自物始也。然弃石入河激
穿牛仔裤可以使你的腿看起来细长、穿上又帅又酷真是显瘦,适合各种场合,使线条优美迷人。牛仔裤的穿戴增加了女性的自信,很容易将精微的身材塑造得低调而不拘束,牛仔的弹性很大,腰部设计更薄。它特别简单大方。穿着高跟鞋看起来更整洁,看起来更加的整洁大方。穿上紧
大家好,我是热爱普及腕表知识的自媒体人。致力于做真假对比测评 视频测评 拆解测评等等,为大家传播普及有营养有深度的腕表知识,用知识充实自己在您的玩表之路不被坑, 只为公正评测每一款腕表。很多时候看一个男人的品味如何,一块表足以。喜欢佩戴手表的男人一定相当
对于各种各样的身材,不足的身材有千万种,但是完美的身材只有一种,对于多变的身材如何才能穿出美感?相信这是每个女孩都关注的,今天跟大家说普遍人都会遇到的问题。圆脸在这个锥子脸盛行的年代里,人们恨不得不自己的脸都削成尖的,圆脸总是给人一种胖胖的感觉,并不
随着美国的一纸禁令,全面禁止向中兴通讯销售零部件、商品、软件和技术七年,隐藏在其中最为关键的点,其实就两个字,“芯片”,当下正是中美贸易战逐渐白热化的当口,我们却悲哀的发现,中兴这家国内仅次于华为的通讯巨无霸,在海外拥有6.8万余件全球专利申请,已授权专
1光电1502“科技创新活力团支部”嘘~我们很低调的学年“五四评优”先进团支部评选活动在前段时间落下帷幕产生了很多获得 先进团支部 称号的班级光电1502班集体 就是在此番龙争虎斗中脱颖而出的一个优秀团支部竞选时 他们分享了本班丰硕的科技成果是的,109个奖
在CAD制图中,我们经常会使用的圆对象,这里教初学者绘制圆的简单方法,以及对圆对象的一些设置,希望可以帮助到小伙伴。一、如何绘制圆对象圆是一种几何图形,在生活中经常可见,CAD制图时,圆也是其中的必备元素,下面教大家使用迅捷CAD编辑器专业版画圆的方法。运行软
纵谈天下事,洞彻古今情,穿越历史长河的重重迷雾,探寻尘封已久的时光典藏,我是百家号“城会玩的历史”的小编 。同治三年(1864年)正月,攻克钟山,合围天京。7月,湘军攻破天京,对无辜平民展开屠杀与抢掠。当时的南京城被烧毁,平民死伤无数,南京人称曾国藩、曾国
小君说说史,今天给大家带来大将军韩信手握三十万大军,不与刘邦三分天下,却死在女人手上!原因很简单,韩信手中三十万大军有大半听令于刘邦。韩信统兵以来,手中唯一一次手握三十万大军,还是在垓下之战围攻项羽时,是刘邦临时任命韩信为军队的作战指挥官,刘邦让韩信
四连板华锋股份 半导体 。金田路霸气8000手封板,可惜11点22分被4087手大单炸开。搞不懂为什么这么喜欢大单一笔炸,很爽吗?就不能小单慢慢出?这样炸很伤市场人气。想出早盘早点出呗,熬到最后出严重打击市场人气。好在后面还是封住了。这票要走出来最好周一装怂,待市
满心科技创始人赵荣庚富士康为何会与一家创业公司合作,并帮助其生产产品?满心科技创始人赵荣庚给出的答案是:团队研制的手机新零售智能终端,不仅仅是一款单纯的自动售货机。它还集成实物销售、虚拟商品销售、增值服务、导客系统等多种功能。此外产品还可保证货品安全
今日手机爆料大神Evan Blass公布了新一代的华为Y3、Y5 Prime和Y6的照片,这三款手机都是定位入门级别,一起来看下。华为Y3这几款手机与过去华为中低端手机的设计风格接近,其中华为Y3显示屏为16:9比例,其余两款机型为18:9比例。华为Y3后置单摄像头,闪光灯与扬声器在
深度 | 原创 | 分析互联网重大事件作者:贺博特朗普正式出手了!任正非六年前的预言,一语成缄!北京时间日,美国商务部突然宣布,未来7年将禁止美国公司向中兴通讯销售任何零部件、商品、软件和技术。不仅如此,就连手机段的安卓系统也要停止合作!
防晒霜几小时补涂一次防晒霜补涂的时间其实并不是确定的,而是需要根据大家购买的防晒霜的SPF值,还有大家所处的环境等来决定的哟~SPF值防晒霜的SPF值指的是防晒霜抵挡紫外线UVB的能力,即防止肌肤晒伤的能力,一般来说spf只越高的防晒霜防护紫外线UVB的时间也就会越长。
杨子姗质感街拍 轻松诠释法式时髦佟丽娅素颜现身机场 肤白貌美十分亮眼近日,“中国乳神”王李丹妮曝光一组餐厅时尚街拍美照~~~在照片中的王李丹妮一改往日柔情御姐形象,一头垂顺的秀发散落在肩,加上淡雅的妆容点缀,活力清爽之感让人眼前一亮,身着一件清新的淡蓝波点
我这个人天生就喜欢长相精明的人,所以我交的朋友都是精气神比较足的,唯独我,因为一双单眼皮,显得特别慵懒,一天天就和没睡醒一样,有时候照镜子都讨厌自己,现在有条件了,第一件事就是改变!身边也不乏有一些爱美整形的朋友,都跟我说完美100对每位求美者都很负责任您需要通过验证再能继续浏览 3秒后开始验证
丨 粤ICP备号-10 丨 新三板上市公司威锋科技(836555)
增值电信业务经营许可证:
Powered by Discuz!
(C) Joyslink Inc. All rights reserved 保留所有权利C/C++/Go Linux/Web 全栈之路
后台开发基础
linux和os:
*、netstat tcpdump ipcsipcrm & & &
*、cpu内存硬盘等等与系统性能调试相关的命令&
*、设置修改权限tcp网络状态查看各进程状态抓包相关等相关命令 &&tcpdump netstat ps……awk sed需掌握
*、共享内存的使用实现原理 & & & &&&
*、c++进程内存空间分布(注意各部分的内存地址谁高谁低,注意栈从高道低分配,堆从低到高分配)
*、ELF是什么?其大小与程序中全局变量的是否初始化有什么关系(注意.bss段)
*、使用过哪些进程间通讯机制,并详细说明(重点)
*、makefile编写,虽然比较基础,但是会被问到
*、gdb调试相关的经验,会被问到
*、如何定位内存泄露?&&也可以用top实时观察
*、动态链接和静态链接的区别
、32位系统一个进程最多多少堆内存
*、多线程和多进程的区别&
*、写一个c程序辨别系统是64位&or32位,辨别系统是大端or小端字节序
*、信号:列出常见的信号,信号怎么处理? &&
*、i++是否原子操作?并解释为什么?
*、说出你所知道的各类linux系统的各类同步机制(重点),什么是死锁?如何避免死锁(每个技术面试官必问)&
*、exit()_exit()的区别
*、如何实现守护进程?
*、linux的内存管理机制是什么? &&
*、linux的任务调度机制是什么?
*、标准库函数和系统调用的区别?
*、系统如何将一个信号通知到进程?
&、宏定义和展开(必须精通)
&、位操作(必须精通)
&、指针操作和计算(必须精通)
&、内存分配(必须精通)
&、sizeof必考
&、各类库函数必须非常熟练的实现
&、哪些库函数属于高危函数,为什么?(strcpy等等)
c++:
%、一个String类的完整实现必须很快速写出来(注意:赋值构造,operator=是关键)
%、虚函数的作用和实现原理(必问必考,实现原理必须很熟)
%、sizeof一个类求大小(注意成员变量,函数,虚函数,继承等等对大小的影响)
%、指针和引用的区别(一般都会问到)
%、多重类构造和析构的顺序
%、stl各容器的实现原理(必考)
%、extern c&是干啥的,(必须将编译器的函数名修饰的机制解答的很透彻)
%、volatile是干啥用的,(必须将cpu的寄存器缓存机制回答的很透彻)
volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。
%、static const等等的用法,(能说出越多越好)
数据结构或者算法:
#、《离散数学》范围内的一切问题皆由可能被深入问到(这个最坑爹,最重要,最体现功底,最能加分,特别是各类树结构的实现和应用)
#、各类排序:大根堆的实现,快排(如何避免最糟糕的状态?),bitmap的运用等等
#、hash,任何一个技术面试官必问(例如为什么一般hashtable的桶数会取一个素数?如何有效避免hash结果值的碰撞)
网络编程:
$、tcp与udp的区别(必问)
$、udp调用connect有什么作用?
1:UDP中可以使用connect系统调用
2:UDP中connect操作与TCP中connect操作有着本质区别.TCP中调用connect会引起三次握手,client与server建立连结.UDP中调用connect内核仅仅把对端ip&port记录下来.
3:UDP中可以多次调用connect,TCP只能调用一次connect.UDP多次调用connect有两种用途:1,指定一个新的ip&port连结.2,断开和之前的ip&port的连结.指定新连结,直接设置connect第二个参数即可.断开连结,需要将connect第二个参数中的sin_family设置成&AF_UNSPEC即可.&
4:UDP中使用connect可以提高效率.原因如下:普通的UDP发送两个报文内核做了如下:#1:建立连结#2:发送报文#3:断开连结#4:建立连结#5:发送报文#6:断开连结
采用connect方式的UDP发送两个报文内核如下处理:#1:建立连结#2:发送报文#3:发送报文另外一点,每次发送报文内核都由可能要做路由查询.5:采用connect的UDP发送接受报文可以调用send,write和recv,read操作.当然也可以调用sendto,recvfrom.调用sendto的时候第五个参数必须是NULL,第六个参数是0.调用recvfrom,recv,read系统调用只能获取到先前connect的ip&port发送的报文.&
UDP中使用connect的好处:1:会提升效率.前面已经描述了.2:高并发服务中会增加系统稳定性.原因:假设client
A&通过非connect的UDP与server
B,C通信.B,C提供相同服务.为了负载均衡,我们让A与B,C交替通信.A与&B通信IPa:PORTa
&----& IPb:PORTbA与&C通信IPa:PORTa'
&----&IPc:PORTc&
假设PORTa与&PORTa'相同了(在大并发情况下会发生这种情况),那么就有可能出现A等待B的报文,却收到了C的报文.导致收报错误.解决方法内就是采用connect的UDP通信方式.在A中创建两个udp,然后分别connect到B,C.
$、tcp连接中时序图,状态图,必须非常非常熟练
$、socket服务端的实现,select和epoll的区别(必问)
select的本质是采用32个整数的32位,即32*32= 1024来标识,fd值为1-1024。当fd的值超过1024限制时,就必须修改FD_SETSIZE的大小。这个时候就可以标识32*max值范围的fd。
对于单进程多线程,每个线程处理多个fd的情况,select是不适合的。
1.所有的线程均是从1-32*max进行扫描,每个线程处理的均是一段fd值,这样做有点浪费
2.1024上限问题,一个处理多个用户的进程,fd值远远大于1024
所以这个时候应该采用poll,
poll传递的是数组头指针和该数组的长度,只要数组的长度不是很长,性能还是很不错的,因为poll一次在内核中申请4K(一个页的大小来存放fd),尽量控制在4K以内
epoll还是poll的一种优化,返回后不需要对所有的fd进行遍历,在内核中维持了fd的列表。select和poll是将这个内核列表维持在用户态,然后传递到内核中。但是只有在2.6的内核才支持。
epoll更适合于处理大量的fd&,且活跃fd不是很多的情况,毕竟fd较多还是一个串行的操作
$、epoll哪些触发模式,有啥区别?(必须非常详尽的解释水平触发和边缘触发的区别,以及边缘触发在编程中要做哪些更多的确认)
$、大规模连接上来,并发模型怎么设计
$、tcp结束连接怎么握手,time_wait状态是什么,为什么会有time_wait状态?哪一方会有time_wait状态,如何避免time_wait状态占用资源(必须回答的详细)
$、tcp头多少字节?哪些字段?(必问)
$、什么是滑动窗口
TCP中采用滑动窗口来进行传输控制,滑动窗口的大小意味着接收方还有多大的缓冲区可以用于接收数据。发送方可以通过滑动窗口的大小来确定应该发送多少字节的数据。当滑动窗口为0时,发送方一般不能再发送数据报,但有两种情况除外,一种情况是可以发送紧急数据,例如,允许用户终止在远端机上的运行进程。另一种情况是发送方可以发送一个1字节的数据报来通知接收方重新声明它希望接收的下一字节及发送方的滑动窗口大小。
TCP的特点之一是提供体积可变的滑动窗口机制,支持端到端的流量控制。TCP的窗口以字节为单位进行调整,以适应接收方的处理能力。处理过程如下:&减小窗口尺寸(1)TCP连接阶段,双方协商窗口尺寸,同时接收方预留数据缓存区;
  (2)发送方根据协商的结果,发送符合窗口尺寸的数据字节流,并等待对方的确认;
  (3)发送方根据确认信息,改变窗口的尺寸,增加或者减少发送未得到确认的字节流中的字节数。调整过程包括:如果出现发送拥塞,发送窗口缩小为原来的一半,同时将超时重传的时间间隔扩大一倍。
  滑动窗口机制为端到端设备间的数据传输提供了可靠的流量控制机制。然而,它只能在源端设备和目的端设备起作用,当网络中间设备(例如路由器等)发生拥塞时,滑动窗口机制将不起作用。
$、connect会阻塞,怎么解决?
(必考必问,提示:设置非阻塞,返回之后用select检测状态)
最通常的方法最有效的是加定时器;也可以采用非阻塞模式。
如果select返回可读,结果只读到0字节,什么情况?
$、keepalive
$、列举你所知道的tcp选项,并说明其作用。
$、socket什么情况下可读?
A socket isready for reading if any of thefollowing four conditions is true:
a. The number ofbytes of data in the socketreceive buffer is greater than or
&&&& equal to thecurrent size of the low-watermark for the socket receive buffer.
&&&& A read operationon the socket will notblock and will return a value greater than 0
b.& The read half of the connectionsis closed(i.e., A TCP connection that has received a FIN).
&&&& A read operationon the socket will notblock and will return 0 (i.e., EOF)
c. The socket isa listening socket and thenumber of completed connection is nonzero.
&&& An accept on thelistening socket willnormally not block, although we will describea&&
d. A socketerror is pending. A readoperation on the socket will not block and will return
&&& an error (-1) with errnoset to thespecific error condition
@、,会考sql语言,服务器数据库大规模数据怎么设计,db各种性能指标
@、最后:补充一个最最重要,最最坑爹,最最有难度的一个题目:一个每秒百万级访问量的互联网服务器,每个访问都有数据计算和I/O操作,如果让你设计,你怎么设计?
腾讯二面:
1、在数据库中如何创建一个表
解答:在数据库中对表的操作有 创建:create table 表名 ;删除:drop table 表名
2、创建后如何添加一个记录、删除一个记录
解答:添加一条记录:insert into 表名 (字段1,字段2) values (值1,值2)
&&&&& & & 删除一条记录:delete from 表名 where 条件
&&&&& & & 更改一条记录:update 表名 set 字段1=值1,字段2=值2 where 条件
3、编写C++中的两个类 一个只能在栈中分配空间 一个只能在堆中分配。 &
(1)代码如下
(2)堆栈分配内存的介绍
一、一个经过编译的C/C++的程序占用的内存分成以下几个部分:
1、栈区(stack):由编译器自动分配和释放 ,存放函数的参数值、局部变量的值等,甚至函数的调用过程都是用栈来完成。其操作方式类似于数据结构中的栈。
2、堆区(heap) :一般由程序员手动申请以及释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式类似于链表。
3、全局区(静态区)(static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统释放空间。&
4、文字常量区:常量字符串就是放在这里的。 程序结束后由系统释放空间。
5、程序代码区:存放函数体的二进制代码。
下面的例子可以完全展示不同的变量所占的内存区域:
//main.cpp
int&a&=&0; 全局初始化区
char&*p1; 全局未初始化区
&&&int&b;&//栈中
char&s[]&=&&abc&;&//栈中
char&*p2;&//栈中
char&*p3&=&&123456&;&//在常量区,p3在栈上
static&int&c&=0;&//全局(静态)初始化区
//以下分配得到的10和20字节的区域就在堆区
p1&=&(char&*)malloc(10);
&&&p2&= new char[20];//(char&*)malloc(20);
strcpy(p1,&&123456&);&//放在常量区,编译器可能会将它与p3所指向的&123456&优化成一个地方。
二、栈(stack)和堆(heap)具体的区别。
1、在申请方式上
栈(stack): 现在很多人都称之为堆栈,这个时候实际上还是指的栈。它由编译器自动管理,无需我们手工控制。 例如,声明函数中的一个局部变量 int b 系统自动在栈中为b开辟空间;在调用一个函数时,系统自动的给函数的形参变量在栈中开辟空间。
堆(heap): 申请和释放由程序员控制,并指明大小。容易产生memory leak。
在C中使用malloc函数。
如:p1 = (char *)malloc(10);
在C++中用new运算符。
如:p2 = new char[20];//(char *)malloc(10);
但是注意p1本身在全局区,而p2本身是在栈中的,只是它们指向的空间是在堆中。
2、申请后系统的响应上
栈(stack):只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。
堆(heap): 首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时, 会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete或free语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。
3、申请大小的限制
栈(stack):在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。 例如,在VC6下面,默认的栈空间大小是1M(好像是,记不清楚了)。当然,我们可以修改:打开工程,依次操作菜单如下:Project-&Setting-&Link,在Category
中选中Output,然后在Reserve中设定堆栈的最大值和commit。
注意:reserve最小值为4Byte;commit是保留在虚拟内存的页文件里面,它设置的较大会使栈开辟较大的值,可能增加内存的开销和启动时间。
堆(heap): 堆是向高地址扩展的数据结构,是不连续的内存区域(空闲部分用链表串联起来)。正是由于系统是用链表来存储空闲内存,自然是不连续的,而链表的遍历方向是由低地址向高地址。一般来讲在32位系统下,堆内存可以达到4G的空间,从这个角度来看堆内存几乎是没有什么限制的。由此可见,堆获得的空间比较灵活,也比较大。
4、分配空间的效率上
栈(stack):栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。但程序员无法对其进行控制。
堆(heap):是C/C++函数库提供的,由new或malloc分配的内存,一般速度比较慢,而且容易产生内存碎片。它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。这样可能引发用户态和核心态的切换,内存的申请,代价变得更加昂贵。显然,堆的效率比栈要低得多。
5、堆和栈中的存储内容
栈(stack):在函数调用时,第一个进栈的是主函数中子函数调用后的下一条指令(子函数调用语句的下一条可执行语句)的地址,然后是子函数的各个形参。在大多数的C编译器中,参数是由右往左入栈的,然后是子函数中的局部变量。注意:静态变量是不入栈的。 当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中子函数调用完成的下一条指令,程序由该点继续运行。
堆(heap):一般是在堆的头部用一个字节存放堆的大小,堆中的具体内容有程序员安排。
6、存取效率的比较
这个应该是显而易见的。拿栈上的数组和堆上的数组来说:
void&main()
&&&int&arr[5]={1,2,3,4,5};
&&&int&*arr1;
&&&arr1=new&int[5];
&&&for&(int&j=0;j&=4;j++)
&&&arr1[j]=j+6;
&&&int&a=arr[1];
&&&int&b=arr1[1];
上面代码中,arr1(局部变量)是在栈中,但是指向的空间确在堆上,两者的存取效率,当然是arr高。因为arr[1]可以直接访问,但是访问arr1[1],首先要访问数组的起始地址arr1,然后才能访问到arr1[1]。
总而言之,言而总之:
堆和栈的区别可以用如下的比喻来看出:
使用栈就象我们去饭馆里吃饭,只管点菜(声明变量)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。
使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。
4、请编写实现malloc()内存分配函数功能一样的代码。&
5、请编写能直接实现strstr()函数功能的代码。&
包含文件:string.h
函数名: strstr
函数原型:extern char *strstr(char *str1, char *str2);
功能:从字符串str1中查找是否有字符串str2,如果有,从str1中的str2位置起,返回str1的指针,如果没有,返回null。
返回值:返回该位置的,如找不到,返回空指针。
charstr[]=&1234
str1=strstr(str,&34&);
cout&&str1&&
显示:& & 34 xyz
  1.Copyright 1990 Software Development Systems, Inc.
char*strstr(constchar*s1,
constchar*s2
 intlen2;
!(len2 == strlen(s2))
 return(char*)s1;
; *s1; ++s1 )
*s1 == *s2 && strncmp(
s1, s2, len2 )==0 )
&& return(char*)s1;
 returnNULL;
函数名: strncmp
功 能: 串比较
用 法: int strncmp(char *str1, char *str2, int maxlen);
说明:此函数功能即比较串str1和str2的前maxlen个字符。如果前maxlen完全相等,返回值就=0;在前maxlen字节比较过程中,如果出现str1[n]与str2[n]不等,则返回(str1[n]-str2[n])。
6、已知: 每个飞机只有一个油箱, 飞机之间可以相互加油(注意是相互,没有加油机) 一箱油可供一架飞机绕地球飞半圈, 问题:为使至少一架飞机绕地球一圈回到起飞时的飞机场,至少需要出动几架飞机?(所有飞机从同一机场起飞,而且必须安全返回机场,不允许中途降落,中间没有飞机场)
7、static的作用——再一次出现~
8、写string类的构造,析构,拷贝函数——这题大约出现过4次左右,包括编程和程序填空,程序员面试宝典上有这题,也算是个经典笔试题,出现几率极大~
#include &iostream&
#include &string.h&
class String
String(const char* str=NULL) & & &//构造函数
if (str==NULL)
m_data=new char[1]; &//即使为空字符串也有一个‘\0’
m_data='\0';
int length = strlen(str);
m_data=new char[length+1];
strcpy(m_data,str);
delete[] m_
String(const String& other)
int length=strlen(other.m_data);
m_data=new char[length+1];
strcpy(m_data,other.m_data);
String& operator=(const String& other)
if (this==&other) &//防止自复制
delete[] m_ &//释放原有资源
int length = strlen( other.m_data ); & & &
m_data = new char[length+1]; //加分点:对m_data加NULL 判断
strcpy( m_data, other.m_data ); &&
return * //得分点:返回本对象的引用 &
能够准确无误地编写出String类的构造函数、拷贝构造函数、赋值函数和析构函数的面试者至少已经具备了C++基本功的60%以上!在这个类中包括了指针类成员变量m_data,当类中包括指针类成员变量时,一定要重载其拷贝构造函数、赋值函数和析构函数,这既是对C++程序员的基本要求,也是《Effective C++》中特别强调的条款。仔细学习这个类,特别注意加注释的得分点和加分点的意义,这样就具备了60%以上的C++基本功!
参考地址:
简单归纳:fd只是一个整数,在open时产生。起到一个索引的作用,进程通过PCB中的文件描述符表找到该fd所指向的文件指针filp。
文件描述符的操作(如: open)返回的是一个文件描述符,内核会在每个进程空间中维护一个文件描述符表, 所有打开的文件都将通过此表中的文件描述符来引用;&
而流(如: fopen)返回的是一个FILE结构指针, FILE结构是包含有文件描述符的,FILE结构函数可以看作是对fd直接操作的系统调用的封装, 它的优点是带有I/O缓存
每个进程在PCB(Process Control Block)即进程控制块中都保存着一份文件描述符表,文件描述符就是这个表的索引,文件描述表中每个表项都有一个指向已打开文件的指针&,现在我们明确一下:已打开的文件在内核中用file结构体表示,文件描述符表中的指针指向file结构体。
linux&和&os:
netstat&:&显示网络状态
Netstat 命令用于显示各种网络相关信息,如网络连接,路由表,接口状态 (Interface Statistics),masquerade 连接,多播成员 (Multicast Memberships) 等等。
从整体上看,netstat的输出结果可以分为两个部分:
一个是Active Internet connections,称为有源TCP连接,其中&Recv-Q&和&Send-Q&指%0A的是接收队列和发送队列。这些数字一般都应该是0。如果不是则表示软件包正在队列中堆积。这种情况只能在非常少的情况见到。
另一个是Active UNIX domain sockets,称为有源Unix域套接口(和网络套接字一样,但是只能用于本机通信,性能可以提高一倍)。&
Proto显示连接使用的协议,RefCnt表示连接到本套接口上的进程号,Types显示套接口的类型,State显示套接口当前的状态,Path表示连接到套接口的其它进程使用的路径名。
tcpdump&:&主要是截获通过本机网络接口的数据,用以分析。能够截获当前所有通过本机网卡的数据包。它拥有灵活的过滤机制,可以确保得到想要的数据。
用简单的话来定义tcpdump,就是:dump the traffic on a network,根据使用者的定义对网络上的数据包进行截获的包分析工具。&tcpdump可以将网络中传送的数据包的“头”完全截获下来提供分析。它支持针对网络层、协议、主机、网络或端口的过滤,并提供and、or、not等逻辑语句来帮助你去掉无用的信息。
ipcs&:检查系统上共享内存的分配
报告进程间通信设施状态。
ipcs 命令往标准输出写入一些关于活动进程间通信设施的信息。如果没有指定任何标志,ipcs 命令用简短格式写入一些关于当前活动&&、&&段、&、远程队列和本地队列标题。
Linux&下&ipcs&指令的用法详解。&ipcs&是&Linux&下显示进程间通信设施状态的工具。可以显示消息队列、共享内存和信号量的信息。对于程序员可能更有用些,普通的系统管理员一般用不到此指令。
ipcrm&:手动解除系统上共享内存的分配
删除消息队列、信号集、或者共享内存标识。
(如果这四个命令没听说过或者不能熟练使用,基本上可以回家,通过的概率较小^_^&,这四个命令的熟练掌握程度基本上能体现面试者实际开发和调试程序的经验&)
查看&cpu&信息
&&&&&&&&#cat /proc/cpuinfo
&&&# cat /proc/meminfo
查看硬盘信息
&&&&&&&&# df -lh
更详细的信息
&&&&&&&&# cat /proc/scsi/scsi
查看网卡信息
&&&&&&&&# dmesg | grep eth
更常用的命令&(&显示系统核心版本号、名称、机器类型等&)
&&&&&&&&# uname -a
cpu&内存&硬盘&等等与系统性能调试相关的命令必须熟练掌握,设置修改权限&tcp&网络状态查看&各进程状态&抓包相关等相关命令&必须熟练掌握
awk sed&需掌握
共享内存的使用实现原理&(必考必问,然后共享内存段被映射进进程空间之后,存在于进程空间的什么位置?共享内存段最大限制是多少?)
$sysctl kern.ipc.shmmax&
kern.ipc.shmmax:
Linux的2.2.x以后的内核版本支持多种共享内存方式,比如:内存映射mmap、POSIX共享内存、System V共享内存;
共享内存定义:共享内存是最快的可用IPC&(进程间通信)形式。它允许多个不相关的进程去访问同一部分逻辑内存。共享内存是由IPC为一个进程创建的一个特殊的地址范围,它将出现在进程的地址空间中。其他进程可以把同一段共享内存段“连接到”它们自己的地址空间里去。所有进程都可以访问共享内存中的地址。如果一个进程向这段共享内存写了数据,所做的改动会立刻被有访问同一段共享内存的其他进程看到。因此共享内存对于数据的传输是非常高效的。
共享内存的原理:共享内存是最有用的进程间通信方式之一,也是最快的IPC&形式。两个不同进程A、B共享内存的意思是,同一块物理内存被映射到进程A、B各自的进程地址空间。进程A可以即时看到进程B对共享内存中数据的更新,反之亦然。
c++&进程内存空间分布(注意各部分的内存地址谁高谁低,注意栈从高到低分配,堆从低到高分配)
ELF&是什么&?其大小与程序中全局变量的是否初始化有什么关系(注意未初始化的数据放在&bss&段)
Linux ELF& ELF = Executable and Linkable Format&,可执行连接格式,是UNIX&系统实验室(USL)作为应用程序二进制接口(Application Binary Interface,ABI)而开发和发布的。扩展名为elf。工具接口标准委员会(TIS)选择了正在发展中的ELF标准作为工作在32位INTEL体系上不同操作系统之间可移植的二进制文件格式。假定开发者定义了一个二进制接口集合,ELF标准用它来支持流线型的软件发展。应该减少不同执行接口的数量。因此可以减少重新编程重新编译的代码。
可执行程序包括BSS段、&&、&&(也称文本段)。
BSS(Block Started by Symbol)通常是指用来存放程序中未初始化的&&和&的一块内存区域。特点是:可读写的,在程序执行之前BSS段会自动清0。所以,未初始的全局变量在程序执行之前已经成0了。
注意和&&的区别,BSS存放的是未初始化的&&和&&,数据段存放的是初始化后的全局变量和静态变量。
UNIX下可使用size命令查看可执行文件的段大小信息。如size a.out。
可执行文件:&包含了代码和数据。具有可执行的程序。
可重定位文件:包含了代码和数据(这些数据是和其他重定位文件和共享的&文件一起连接时使用的)
共享&object&文件(又可叫做共享库):包含了代码和数据(这些数据是在连接&时候被连接器&ld&和运行时动态连接器使用的)。
使创建共享库容易,使动态装载和共享库的结合更加容易。在&ELF&下,在&C++&
中,全局的构造函数和析构函数在共享库和静态库中用同样方法处理。
使用过哪些&进程间通讯机制&,并详细说明(重点)
makefile&编写,虽然比较基础,但是会被问到
vim makefile
hello.o:hello.c hello.h
&&&&&& gcc –c hello.o -Lm
gdb&调试相关的经验,会被问到
GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具。或许,各位比较喜欢那种图形界面方式的,像VC、BCB等IDE的调试,但如果你是在 UNIX平台下做&&,你会发现GDB这个调试工具有比VC、BCB的图形化调试器更强大的功能。所谓“寸有所长,尺有所短”就是这个道理。
一般来说,GDB主要帮助你完成下面四个方面的功能:
1、启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。
2、可让被调试的程序在你所指定的调置的&&处停住。(&&可以是&)
3、当程序被停住时,可以检查此时你的程序中所发生的事。
4、动态的改变你程序的执行环境。
《GDB使用手册》
gcc -g -o hello hello.c 。
GDB常用命令简介&
GDB的命令很多,本文不会全部介绍,仅会介绍一些最常用的。在介绍之前,先介绍GDB中的一个非常有用的功能:补齐功能。它就如同Linux下SHELL中的命令补齐一样。当你输入一个命令的前几个字符,然后输入TAB键,如果没有其它命令的前几个字符与此相同,SHELL将补齐此命令。如果有其它命令的前几个字符与此相同,你会听到一声警告声,再输入TAB键,SHELL将所有前几个字符与此相同的命令全部列出。而GDB中的补齐功能不仅能补齐GDB命令,而且能补齐参数。&
本文将先介绍常用的命令,然后结合一个具体的例子来演示如何实际使用这些命令。下面的所有命令除了第一条启动GDB命令是在SHELL下输入的,其余都是GDB内的命令。大部分GDB内的命令都可以仅输入前几个字符,只要不与其它指令冲突。如quit可以简写为q,因为以q打头的命令只有quit。List可以简写为l,等等&
3.1 启动GDB&
你可以输入GDB来启动GDB程序。GDB程序有许多参数,在此没有必要详细介绍,但一个最为常用的还是要介绍的:如果你已经编译好一个程序,我们假设文件名为hello,你想用GDB调试它,可以输入gdb hello来启动GDB并载入你的程序。如果你仅仅启动了GDB,你必须在启动后,在GDB中再载入你的程序。&
3.2 载入程序 === file&
在GDB内,载入程序很简单,使用file命令。如file hello。当然,程序的路径名要正确。&
退出GDB === quit&
在GDB的命令方式下,输入quit,你就可以退出GDB。你也可以输入'C-d'来退出GDB。&
3.3 运行程序 === run&
当你在GDB中已将要调试的程序载入后,你可以用run命令来执行。如果你的程序需要参数,你可以在run指令后接着输入参数,就象你在SHELL下执行一个需要参数的命令一样。&
3.4 查看程序信息 === info&
info指令用来查看程序的信息,当你用help info查看帮助的话,info指令的参数足足占了两个屏幕,它的参数非常多,但大部分不常用。我用info指令最多的是用它来查看断点信息。&
3.4.1 查看断点信息&
br是断点break的缩写,记得GDB的补齐功能吧。用这条指令,你可以得到你所设置的所有断点的详细信息。包括断点号,类型,状态,内存地址,断点在源程序中的位置等。&
3.4.2 查看当前源程序&
info source&
3.4.3 查看堆栈信息&
info stack&
用这条指令你可以看清楚程序的调用层次关系。&
3.4.4 查看当前的参数&
info args&
3.5 列出源一段源程序 === list&
3.5.1 列出某个函数&
list FUNCTION&
3.5.2 以当前源文件的某行为中间显示一段源程序&
list LINENUM&
3.5.3 接着前一次继续显示&
3.5.4 显示前一次之前的源程序&
3.5.5 显示另一个文件的一段程序&
list FILENAME:FUNCTION 或 listFILENAME:LINENUM&
3.6 设置断点 === break&
现在我们将要介绍的也许是最常用和最重要的命令:设置断点。无论何时,只要你的程序已被载入,并且当前没有正在运行,你就能设置,修改,删除断点。设置断点的命令是break。有许多种设置断点的方法。如下:&
3.6.1 在函数入口设置断点
如何定位内存泄露?
内存泄漏是指堆内存的泄漏。堆内存是指程序从堆中分配的、大小任意的(内存块的大小可以在程序运行期决定)、使用完后必须显示释放的内存。应用程序一般使用malloc&、&realloc&、&new&等函数从堆中分配到一块内存,使用完后,程序必须负责相应的调用&free&或&delete&释放该内存块。否则,这块内存就不能被再次使用,我们就说这块内存泄漏了。
C++&程序缺乏相应的手段来检测内存信息,只能使用&top&指令观察进程的动态内存总额。而且程序退出时,我们无法获知任何内存泄漏信息
使用&Linux&命令回收内存,可以使用&ps&、&kill&两个命令检测内存使用情况和进行回收。在使用超级用户权限时使用命令&“ps”&,它会列出所有正在运行的程序名称和对应的进程号(&PID&)。&kill&命令的工作原理是向&Linux&操作系统的内核送出一个系统操作信号和程序的进程号(&PID&)
动态链接和静态链接的区别
动态链接是指在生成可执行文件时不将所有程序用到的函数链接到一个文件,因为有许多函数在操作系统带的dll文件中,当程序运行时直接从操作系统中找。 而静态链接就是把所有用到的函数全部链接到exe文件中。
动态链接是只建立一个引用的接口,而真正的代码和数据存放在另外的可执行模块中,在运行时再装入;而静态链接是把所有的代码和数据都复制到本模块中,运行时就不再需要库了。
32&位系统一个进程最多有多少堆内存
多线程和多进程的区别(重点&面试官最最关心的一个问题,必须从&cpu&调度,上下文切换,数据共享,多核&cup&利用率,资源占用,等等各方面回答,然后有一个问题必须会被问到:哪些东西是一个线程私有的?答案中必须包含寄存器,否则悲催)
我们按照多个不同的维度,来看看多进程和多线程的对比(注:都是相对的,不是说一个好得不得了,另一个差的无法忍受)
数据共享、同步
数据是分开的&:&共享复杂,需要用&IPC;&同步简单
多线程共享进程数据:共享简单;同步复杂
内存、&CPU
占用内存多,切换复杂,&CPU&利用率低
占用内存少,切换简单,&CPU&利用率高
创建销毁、切换
创建销毁、切换复杂,速度慢&&
创建销毁、切换简单,速度快&&
线程占优&&
编程简单,调试简单
编程复杂,调试复杂
进程占优&&
进程间不会相互影响&&
一个线程挂掉将导致整个进程挂掉
适应于多核、多机分布&;如果一台机器不够,扩展到多台机器比较简单
适应于多核分布
然后我们来看下线程和进程间的比较
子进程继承父进程的属性:
子线程继承主线程的属性:
实际用户&ID&,实际组&ID,有效用户&ID&,有效组&ID;
附加组&ID&;
进程组&ID&;
会话&ID&;
控制终端;
设置用户&ID&标志和设置组ID&标志;
当前工作目录;
文件模式创建屏蔽字(&umask&);
信号屏蔽和安排;
针对任一打开文件描述符的在执行时关闭(&close-on-exec&)标志;
连接的共享存储段;
存储映射;
资源限制;
进程中的所有信息对该进程的所有线程都是共享的;
可执行的程序文本;
程序的全局内存;
文件描述符;
信号的处理是进程中所有线程共享的(注意:如果信号的默认处理是终止该进程那么即是把信号传给某个线程也一样会将进程杀掉);
父子进程之间的区别:
子线程特有的:
fork&的返回值&(=0&子进程&);
进程&ID&不同;
两个进程具有不同的父进程&ID&;
子进程的&tms_utime,tms_stime,tms_cutime&以及&tms_ustime&均被设置为&0&;
不继承父进程设置的文件锁;
子进程的未处理闹钟被清除;
子进程的未处理信号集设置为空集;
线程&ID&;
一组寄存器值;
调度优先级和策略;
信号屏蔽字;
errno&变量;
线程私有数据;
1)&需要频繁创建销毁的优先用线程。&实例:&web&服务器。来一个建立一个线程,断了就销毁线程。要是用进程,创建和销毁的代价是很难承受的。&2&)需要进行大量计算的优先使用线程。&所谓大量计算,当然就是要消耗很多&cpu&,切换频繁了,这种情况先线程是最合适的。&实例:图像处理、算法处理&3&)强相关的处理用线程,若相关的处理用进程。&什么叫强相关、弱相关?理论上很难定义,给个简单的例子就明白了。&一般的&server&需要完成如下任务:消息收发和消息处理。消息收发和消息处理就是弱相关的任务,而消息处理里面可能又分为消息解码、业务处理,这两个任务相对来说相关性就要强多了。因此消息收发和消息处理可以分进程设计,消息解码和业务处理可以分线程设计。&4&)可能扩展到多机分布的用进程,多核分布的用线程。&5)都满足需求的情况下,用你最熟悉、最拿手的方式。
至于&”&数据共享、同步&“&、&“&编程、调试&”&、&“&可靠性&”&这几个维度的所谓的&“&复杂、简单&”&应该怎么取舍,只能说:没有明确的选择方法。一般有一个选择原则:如果多进程和多线程都能够满足要求,那么选择你最熟悉、最拿手的那个。
一般运行一个程序称为一个进程。&进程可以创建线程,也可以创建进程。&线程是由进程管理的,线程之间、线程和父进程(创建线程的进程)之间可以共享内存变量(需要使用策略的)。&进程之间一般不可以直接共享内存变量,需要使用一些进程间的控制共享内存变量。&如果你使用并行计算,建议使用线程。
进程是个容器或者说资源管理者,有独立的内存地址空间。&线程依赖于它所在的进程,共享进程的资源和内存地址空间。&特别是&linux&里面,线程与进程接近;&windows的进程完全是个容器,线程更轻量级。具体可以了解&linux&下的&fork&以及&clone&,&windows&的&createprocess&、&createthread&等
什么是进程。最直观的就是一个个pid,官方的说法就:进程是程序在计算机上的一次执行活动。
主要参看&2&篇博文:
还有就是谢老师写的《计算机网络》第五版,&.TCP/IP&详解&(&卷一,卷二&)&以及《&Unix&网络编程》以及&Linux&源代码之外,&RFC
一、概念:
key:TCP&是一种面向连接的、可靠的、字节流服务
1.&面向链接:&TCP&面向链接,面向连接意味着两个使用&TCP&的应用(通常是一个客户和一个服务器)在彼此交换数据之前必须通过三次握手先建立一个&TCP&连接。在一个&TCP&中仅有两方彼此通信,多播和广播不能用于&TCP&。&UDP&是不可靠的传输,传输前不需要建立链接,可以应用多播和广播实现一对多的通信。
2.&可靠性:&TCP&提供端到端的流量控制,对收到的数据进行确认,采用超时重发,对失序的数据进行重新排序等机制保证数据通信的可靠性。而&UDP&是一种不可靠的服务,接收方可能不能收到发送方的数据报。
3.TCP&是一种流模式的协议,&UDP&是一种数据报模式的协议。进程的每个输出操作都正好产生一个&UDP&数据报,并组装成一份待发送的&IP&数据报。&TCP&应用程序产生的全体数据与真正发送的单个&IP&数据报可能没有什么联系。&TCP&会有粘包和半包的现象。
4.&效率上:速度上,一般&TCP&速度慢,传输过程中需要对数据进行确认,超时重发,还要对数据进行排序。&UDP&没有这些机制所以速度快。数据比例,&TCP&头至少20&个字节,&UDP&头&8&个字节,相对效率高。组装效率上:&TCP&头至少&20&个字节,UDP&头&8&个字节,系统组装上&TCP&相对慢。
5.&用途上:用于&TCP&可靠性,&http&,&ftp&使用。而由于&UDP&速度快,视频,在线游戏多用&UDP&,保证实时性
对于第三点的理解。&TCP&可能发送&100&个&“&包&”&,而接收到&50&个&“&包&”&,不是丢&“&包”&了,而是每次接受的&“&包&”&都比发送的多,其实&TCP&并没有包的概念。例如,每次发10&个字节,可能读得时候一次读了&20&个字节。&TCP&是一种流模式的协议,在接收到的缓存中按照发送的包得顺序自动按照顺序拼接好,因为数据基本来自同一个主机,而且是按照顺序发送过来的,&TCP&的缓存中存放的就是,连续的数据。感觉好像是多封装了一步比&UDP&。而&UDP&因为可能两个不同的主机,给同一个主机发送,(一个端口可能收到多个应用程序的数据),或者按照&TCP&那样合并数据,必然会造成数据错误。我觉得关键的原因还是,&TCP&是面向连接,而&UDP&是无连接的,这就导致,&TCP&接收的数据为一个主机发来且有序无误的,而&UDP&可能是多个主机发来的无序,可能错误的。
写一个&c&程序辨别系统是&16&位&or32&位
法一:&int k=~0;
if((unsigned int)k &63356) cout&&&at least 32bits&&&
else cout&&&16 bits&&&
法二:&//32&为系统
int i=65536;
int j=65535;
写一个&c&程序辨别系统是大端&or&小端字节序
用联合体:如&char&类型的,可以看他输出的是&int&的高字节还是低字节
信号:列出常见的信号,信号怎么处理?
信号是Linux编程中非常重要的部分,本文将详细介绍信号机制的基本概念、Linux对信号机制的大致实现方法、如何使用信号,以及有关信号的几个系统调用。&
信号机制是进程之间相互传递消息的一种方法,信号全称为软中断信号,也有人称作软中断。从它的命名可以看出,它的实质和使用很象中断。所以,信号可以说是进程控制的一部分。&
一、信号的基本概念&
本节先介绍信号的一些基本概念,然后给出一些基本的信号类型和信号对应的事件。基本概念对于理解和使用信号,对于理解信号机制都特别重要。下面就来看看什么是信号。&
1、基本概念&
软中断信号(signal,又简称为信号)用来通知进程发生了异步事件。进程之间可以互相通过系统调用kill发送软中断信号。内核也可以因为内部事件而给进程发送信号,通知进程发生了某个事件。注意,信号只是用来通知某进程发生了什么事件,并不给该进程传递任何数据。&
收 到信号的进程对各种信号有不同的处理方法。处理方法可以分为三类:第一种是类似中断的处理程序,对于需要处理的信号,进程可以指定处理函数,由该函数来处 理。第二种方法是,忽略某个信号,对该信号不做任何处理,就象未发生过一样。第三种方法是,对该信号的处理保留系统的默认值,这种缺省操作,对大部分的信 号的缺省操作是使得进程终止。进程通过系统调用signal来指定进程对某个信号的处理行为。&
在进程表的表项中有一个软中断信号域,该域中每一位对应一个信号,当有信号发送给进程时,对应位置位。由此可以看出,进程对不同的信号可以同时保留,但对于同一个信号,进程并不知道在处理之前来过多少个。&
2、信号的类型&
发出信号的原因很多,这里按发出信号的原因简单分类,以了解各种信号:&
(1) 与进程终止相关的信号。当进程退出,或者子进程终止时,发出这类信号。&
(2) 与进程例外事件相关的信号。如进程越界,或企图写一个只读的内存区域(如程序正文区),或执行一个特权指令及其他各种硬件错误。&
(3) 与在系统调用期间遇到不可恢复条件相关的信号。如执行系统调用exec时,原有资源已经释放,而目前系统资源又已经耗尽。&
(4) 与执行系统调用时遇到非预测错误条件相关的信号。如执行一个并不存在的系统调用。&
(5) 在用户态下的进程发出的信号。如进程调用系统调用kill向其他进程发送信号。&
(6) 与终端交互相关的信号。如用户关闭一个终端,或按下break键等情况。&
(7) 跟踪进程执行的信号。&
Linux支持的信号列表如下。很多信号是与机器的体系结构相关的,首先列出的是POSIX.1中列出的信号:&
信号 值 处理动作 发出信号的原因&
----------------------------------------------------------------------&
SIGHUP 1 A 终端挂起或者控制进程终止&
SIGINT 2 A 键盘中断(如break键被按下)&
SIGQUIT 3 C 键盘的退出键被按下&
SIGILL 4 C 非法指令&
SIGABRT 6 C 由abort(3)发出的退出指令&
SIGFPE 8 C 浮点异常&
SIGKILL 9 AEF Kill信号&
SIGSEGV 11 C 无效的内存引用&
SIGPIPE 13 A 管道破裂: 写一个没有读端口的管道&
SIGALRM 14 A 由alarm(2)发出的信号&
SIGTERM 15 A 终止信号&
SIGUSR1 30,10,16 A 用户自定义信号1&
SIGUSR2 31,12,17 A 用户自定义信号2&
SIGCHLD 20,17,18 B 子进程结束信号&
SIGCONT 19,18,25 进程继续(曾被停止的进程)&
SIGSTOP 17,19,23 DEF 终止进程&
SIGTSTP 18,20,24 D 控制终端(tty)上按下停止键&
SIGTTIN 21,21,26 D 后台进程企图从控制终端读&
SIGTTOU 22,22,27 D 后台进程企图从控制终端写&
下面的信号没在POSIX.1中列出,而在SUSv2列出&
信号 值 处理动作 发出信号的原因&
--------------------------------------------------------------------&
SIGBUS 10,7,10 C 总线错误(错误的内存访问)&
SIGPOLL A Sys V定义的Pollable事件,与SIGIO同义&
SIGPROF 27,27,29 A Profiling定时器到&
SIGSYS 12,-,12 C 无效的系统调用 (SVID)&
SIGTRAP 5 C 跟踪/断点捕获&
SIGURG 16,23,21 B Socket出现紧急条件(4.2 BSD)&
SIGVTALRM 26,26,28 A 实际时间报警时钟信号(4.2 BSD)&
SIGXCPU 24,24,30 C 超出设定的CPU时间限制(4.2 BSD)&
SIGXFSZ 25,25,31 C 超出设定的文件大小限制(4.2 BSD)&
(对于SIGSYS,SIGXCPU,SIGXFSZ,以及某些机器体系结构下的SIGBUS,Linux缺省的动作是A (terminate),SUSv2 是C (terminate and dump core))。&
下面是其它的一些信号&
信号 值 处理动作 发出信号的原因&
----------------------------------------------------------------------&
SIGIOT 6 C IO捕获指令,与SIGABRT同义&
SIGEMT 7,-,7&
SIGSTKFLT -,16,- A 协处理器堆栈错误&
SIGIO 23,29,22 A 某I/O操作现在可以进行了(4.2 BSD)&
SIGCLD -,-,18 A 与SIGCHLD同义&
SIGPWR 29,30,19 A 电源故障(System V)&
SIGINFO 29,-,- A 与SIGPWR同义&
SIGLOST -,-,- A 文件锁丢失&
SIGWINCH 28,28,20 B 窗口大小改变(4.3 BSD, Sun)&
SIGUNUSED -,31,- A 未使用的信号(will be SIGSYS)&
(在这里,- 表示信号没有实现;有三个值给出的含义为,第一个值通常在Alpha和Sparc上有效,中间的值对应i386和ppc以及sh,最后一个值对应mips。信号29在Alpha上为SIGINFO / SIGPWR ,在Sparc上为SIGLOST。)&
处理动作一项中的字母含义如下&
A 缺省的动作是终止进程&
B 缺省的动作是忽略此信号&
C 缺省的动作是终止进程并进行内核映像转储(dump core)&
D 缺省的动作是停止进程&
E 信号不能被捕获&
F 信号不能被忽略&
上 面介绍的信号是常见系统所支持的。以表格的形式介绍了各种信号的名称、作用及其在默认情况下的处理动作。各种默认处理动作的含义是:终止程序是指进程退 出;忽略该信号是将该信号丢弃,不做处理;停止程序是指程序挂起,进入停止状况以后还能重新进行下去,一般是在调试的过程中(例如ptrace系统调 用);内核映像转储是指将进程数据在内存的映像和进程在内核结构中存储的部分内容以一定格式转储到文件系统,并且进程退出执行,这样做的好处是为程序员提 供了方便,使得他们可以得到进程当时执行时的数据值,允许他们确定转储的原因,并且可以调试他们的程序。&
注意 信号SIGKILL和SIGSTOP既不能被捕捉,也不能被忽略。信号SIGIOT与SIGABRT是一个信号。可以看出,同一个信号在不同的系统中值可能不一样,所以建议最好使用为信号定义的名字,而不要直接使用信号的值。&
二、信 号 机 制&
上 一节中介绍了信号的基本概念,在这一节中,我们将介绍内核如何实现信号机制。即内核如何向一个进程发送信号、进程如何接收一个信号、进程怎样控制自己对信 号的反应、内核在什么时机处理和怎样处理进程收到的信号。还要介绍一下setjmp和longjmp在信号中起到的作用。&
1、内核对信号的基本处理方法&
内 核给一个进程发送软中断信号的方法,是在进程所在的进程表项的信号域设置对应于该信号的位。这里要补充的是,如果信号发送给一个正在睡眠的进程,那么要看 该进程进入睡眠的优先级,如果进程睡眠在可被中断的优先级上,则唤醒进程;否则仅设置进程表中信号域相应的位,而不唤醒进程。这一点比较重要,因为进程检 查是否收到信号的时机是:一个进程在即将从内核态返回到用户态时;或者,在一个进程要进入或离开一个适当的低调度优先级睡眠状态时。&
内核处理一个进程收到的信号的时机是在一个进程从内核态返回用户态时。所以,当一个进程在内核态下运行时,软中断信号并不立即起作用,要等到将返回用户态时才处理。进程只有处理完信号才会返回用户态,进程在用户态下不会有未处理完的信号。&
内 核处理一个进程收到的软中断信号是在该进程的上下文中,因此,进程必须处于运行状态。前面介绍概念的时候讲过,处理信号有三种类型:进程接收到信号后退 出;进程忽略该信号;进程收到信号后执行用户设定用系统调用signal的函数。当进程接收到一个它忽略的信号时,进程丢弃该信号,就象没有收到该信号似 的继续运行。如果进程收到一个要捕捉的信号,那么进程从内核态返回用户态时执行用户定义的函数。而且执行用户定义的函数的方法很巧妙,内核是在用户栈上创 建一个新的层,该层中将返回地址的值设置成用户定义的处理函数的地址,这样进程从内核返回弹出栈顶时就返回到用户定义的函数处,从函数返回再弹出栈顶时,
才返回原先进入内核的地方。这样做的原因是用户定义的处理函数不能且不允许在内核态下执行(如果用户定义的函数在内核态下运行的话,用户就可以获得任何权 限)。&
在信号的处理方法中有几点特别要引起注意。第一,在一些系统中,当一个进程处理完中断信号返回用户态之前,内核清除用户区中设 定的对该信号的处理例程的地址,即下一次进程对该信号的处理方法又改为默认值,除非在下一次信号到来之前再次使用signal系统调用。这可能会使得进程 在调用signal之前又得到该信号而导致退出。在BSD中,内核不再清除该地址。但不清除该地址可能使得进程因为过多过快的得到某个信号而导致堆栈溢 出。为了避免出现上述情况。在BSD系统中,内核模拟了对硬件中断的处理方法,即在处理某个中断时,阻止接收新的该类中断。&
第二个要 引起注意的是,如果要捕捉的信号发生于进程正在一个系统调用中时,并且该进程睡眠在可中断的优先级上,这时该信号引起进程作一次longjmp,跳出睡眠 状态,返回用户态并执行信号处理例程。当从信号处理例程返回时,进程就象从系统调用返回一样,但返回了一个错误代码,指出该次系统调用曾经被中断。这要注 意的是,BSD系统中内核可以自动地重新开始系统调用。&
第三个要注意的地方:若进程睡眠在可中断的优先级上,则当它收到一个要忽略的信号时,该进程被唤醒,但不做longjmp,一般是继续睡眠。但用户感觉不到进程曾经被唤醒,而是象没有发生过该信号一样。&
第 四个要注意的地方:内核对子进程终止(SIGCLD)信号的处理方法与其他信号有所区别。当进程检查出收到了一个子进程终止的信号时,缺省情况下,该进程 就象没有收到该信号似的,如果父进程执行了系统调用wait,进程将从系统调用wait中醒来并返回wait调用,执行一系列wait调用的后续操作(找 出僵死的子进程,释放子进程的进程表项),然后从wait中返回。SIGCLD信号的作用是唤醒一个睡眠在可被中断优先级上的进程。如果该进程捕捉了这个 信号,就象普通信号处理一样转到处理例程。如果进程忽略该信号,那么系统调用wait的动作就有所不同,因为SIGCLD的作用仅仅是唤醒一个睡眠在可被
中断优先级上的进程,那么执行wait调用的父进程被唤醒继续执行wait调用的后续操作,然后等待其他的子进程。&
如果一个进程调用signal系统调用,并设置了SIGCLD的处理方法,并且该进程有子进程处于僵死状态,则内核将向该进程发一个SIGCLD信号。&
2、setjmp和longjmp的作用&
前面在介绍信号处理机制时,多次提到了setjmp和longjmp,但没有仔细说明它们的作用和实现方法。这里就此作一个简单的介绍。&
在 介绍信号的时候,我们看到多个地方要求进程在检查收到信号后,从原来的系统调用中直接返回,而不是等到该调用完成。这种进程突然改变其上下文的情况,就是 使用setjmp和longjmp的结果。setjmp将保存的上下文存入用户区,并继续在旧的上下文中执行。这就是说,进程执行一个系统调用,当因为资 源或其他原因要去睡眠时,内核为进程作了一次setjmp,如果在睡眠中被信号唤醒,进程不能再进入睡眠时,内核为进程调用longjmp,该操作是内核 为进程将原先setjmp调用保存在进程用户区的上下文恢复成现在的上下文,这样就使得进程可以恢复等待资源前的状态,而且内核为setjmp返回1,使
得进程知道该次系统调用失败。这就是它们的作用。&
三、有关信号的系统调用&
前面两节已经介绍了有关信号的大部分知 识。这一节我们来了解一下这些系统调用。其中,系统调用signal是进程用来设定某个信号的处理方法,系统调用kill是用来发送信号给指定进程的。这 两个调用可以形成信号的基本操作。后两个调用pause和alarm是通过信号实现的进程暂停和定时器,调用alarm是通过信号通知进程定时器到时。所 以在这里,我们还要介绍这两个调用。&
1、signal 系统调用&
系统调用signal用来设定某个信号的处理方法。该调用声明的格式如下:&
void (*signal(int signum, void (*handler)(int)))(int);&
在使用该调用的进程中加入以下头文件:&
#include &signal.h&&
上述声明格式比较复杂,如果不清楚如何使用,也可以通过下面这种类型定义的格式来使用(POSIX的定义):&
typedef void (*sighandler_t)(int);&
sighandler_t signal(int signum, sighandler_t handler);&
但这种格式在不同的系统中有不同的类型定义,所以要使用这种格式,最好还是参考一下联机手册。&
在调用中,参数signum指出要设置处理方法的信号。第二个参数handler是一个处理函数,或者是&
SIG_IGN:忽略参数signum所指的信号。&
SIG_DFL:恢复参数signum所指信号的处理方法为默认值。&
传递给信号处理例程的整数参数是信号值,这样可以使得一个信号处理例程处理多个信号。系统调用signal返回值是指定信号signum前一次的处理例程或者错误时返回错误代码SIG_ERR。下面来看一个简单的例子:&
#include &signal.h&&
#include &unistd.h&&
#include &stdio.h&&
void sigroutine(int dunno) { /* 信号处理例程,其中dunno将会得到信号的值 */&
switch (dunno) {&
printf(&Get a signal -- SIGHUP &);&
printf(&Get a signal -- SIGINT &);&
printf(&Get a signal -- SIGQUIT &);&
int main() {&
printf(&process id is %d &,getpid());&
signal(SIGHUP, sigroutine); //* 下面设置三个信号的处理方法&
signal(SIGINT, sigroutine);&
signal(SIGQUIT, sigroutine);&
for (;;) ;&
其中信号SIGINT由按下Ctrl-C发出,信号SIGQUIT由按下Ctrl-发出。该程序执行的结果如下:&
localhost:~$ ./sig_test&
process id is 463&
Get a signal -SIGINT //按下Ctrl-C得到的结果&
Get a signal -SIGQUIT //按下Ctrl-得到的结果&
//按下Ctrl-z将进程置于后台&
[1]+ Stopped ./sig_test&
localhost:~$ bg&
[1]+ ./sig_test &&
localhost:~$ kill -HUP 463 //向进程发送SIGHUP信号&
localhost:~$ Get a signal – SIGHUP&
kill -9 463 //向进程发送SIGKILL信号,终止进程&
localhost:~$&
2、kill 系统调用&
系统调用kill用来向进程发送一个信号。该调用声明的格式如下:&
int kill(pid_t pid, int sig);&
在使用该调用的进程中加入以下头文件:&
#include &sys/types.h&&
#include &signal.h&&
该 系统调用可以用来向任何进程或进程组发送任何信号。如果参数pid是正数,那么该调用将信号sig发送到进程号为pid的进程。如果pid等于0,那么信 号sig将发送给当前进程所属进程组里的所有进程。如果参数pid等于-1,信号sig将发送给除了进程1和自身以外的所有进程。如果参数pid小于- 1,信号sig将发送给属于进程组-pid的所有进程。如果参数sig为0,将不发送信号。该调用执行成功时,返回值为0;错误时,返回-1,并设置相应 的错误代码errno。下面是一些可能返回的错误代码:&
EINVAL:指定的信号sig无效。&
ESRCH:参数pid指定的进程或进程组不存在。注意,在进程表项中存在的进程,可能是一个还没有被wait收回,但已经终止执行的僵死进程。&
EPERM: 进程没有权力将这个信号发送到指定接收信号的进程。因为,一个进程被允许将信号发送到进程pid时,必须拥有root权力,或者是发出调用的进程的UID 或EUID与指定接收的进程的UID或保存用户ID(savedset-user-ID)相同。如果参数pid小于-1,即该信号发送给一个组,则该错误 表示组中有成员进程不能接收该信号。&
3、pause系统调用&
系统调用pause的作用是等待一个信号。该调用的声明格式如下:&
int pause(void);&
在使用该调用的进程中加入以下头文件:&
#include &unistd.h&&
该调用使得发出调用的进程进入睡眠,直到接收到一个信号为止。该调用总是返回-1,并设置错误代码为EINTR(接收到一个信号)。下面是一个简单的范例:&
#include &unistd.h&&
#include &stdio.h&&
#include &signal.h&&
void sigroutine(int unused) {&
printf(&Catch a signal SIGINT &);&
int main() {&
signal(SIGINT, sigroutine);&
printf(&receive a signal &);&
在这个例子中,程序开始执行,就象进入了死循环一样,这是因为进程正在等待信号,当我们按下Ctrl-C时,信号被捕捉,并且使得pause退出等待状态。&
4、alarm和 setitimer系统调用&
系统调用alarm的功能是设置一个定时器,当定时器计时到达时,将发出一个信号给进程。该调用的声明格式如下:&
unsigned int alarm(unsigned int seconds);&
在使用该调用的进程中加入以下头文件:&
#include &unistd.h&&
系 统调用alarm安排内核为调用进程在指定的seconds秒后发出一个SIGALRM的信号。如果指定的参数seconds为0,则不再发送 SIGALRM信号。后一次设定将取消前一次的设定。该调用返回值为上次定时调用到发送之间剩余的时间,或者因为没有前一次定时调用而返回0。&
注意,在使用时,alarm只设定为发送一次信号,如果要多次发送,就要多次使用alarm调用。&
对于alarm,这里不再举例。现在的系统中很多程序不再使用alarm调用,而是使用setitimer调用来设置定时器,用getitimer来得到定时器的状态,这两个调用的声明格式如下:&
int getitimer(int which, struct itimerval *value);&
int setitimer(int which, const struct itimerval *value, struct itimerval*ovalue);&
在使用这两个调用的进程中加入以下头文件:&
#include &sys/time.h&&
该系统调用给进程提供了三个定时器,它们各自有其独有的计时域,当其中任何一个到达,就发送一个相应的信号给进程,并使得计时器重新开始。三个计时器由参数which指定,如下所示:&
TIMER_REAL:按实际时间计时,计时到达将给进程发送SIGALRM信号。&
ITIMER_VIRTUAL:仅当进程执行时才进行计时。计时到达将发送SIGVTALRM信号给进程。&
ITIMER_PROF:当进程执行时和系统为该进程执行动作时都计时。与ITIMER_VIR-TUAL是一对,该定时器经常用来统计进程在用户态和内核态花费的时间。计时到达将发送SIGPROF信号给进程。&
定时器中的参数value用来指明定时器的时间,其结构如下:&
struct itimerval {&
struct timeval it_ /* 下一次的取值 */&
struct timeval it_ /* 本次的设定值 */&
该结构中timeval结构定义如下:&
struct timeval {&
long tv_ /* 秒 */&
long tv_ /* 微秒,1秒 = 1000000 微秒*/&
在setitimer 调用中,参数ovalue如果不为空,则其中保留的是上次调用设定的值。定时器将it_value递减到0时,产生一个信号,并将it_value的值设 定为it_interval的值,然后重新开始计时,如此往复。当it_value设定为0时,计时器停止,或者当它计时到期,而it_interval 为0时停止。调用成功时,返回0;错误时,返回-1,并设置相应的错误代码errno:&
EFAULT:参数value或ovalue是无效的指针。&
EINVAL:参数which不是ITIMER_REAL、ITIMER_VIRT或ITIMER_PROF中的一个。&
下面是关于setitimer调用的一个简单示范,在该例子中,每隔一秒发出一个SIGALRM,每隔0.5秒发出一个SIGVTALRM信号:&
#include &signal.h&&
#include &unistd.h&&
#include &stdio.h&&
#include &sys/time.h&&
void sigroutine(int signo) {&
switch (signo) {&
case SIGALRM:&
printf(&Catch a signal -- SIGALRM &);&
case SIGVTALRM:&
printf(&Catch a signal -- SIGVTALRM &);&
int main() {&
struct itimerval value,ovalue,value2;&
printf(&process id is %d &,getpid());&
signal(SIGALRM, sigroutine);&
signal(SIGVTALRM, sigroutine);&
value.it_value.tv_sec = 1;&
value.it_value.tv_usec = 0;&
value.it_interval.tv_sec = 1;&
value.it_interval.tv_usec = 0;&
setitimer(ITIMER_REAL, &value, &ovalue);&
value2.it_value.tv_sec = 0;&
value2.it_value.tv_usec = 500000;&
value2.it_interval.tv_sec = 0;&
value2.it_interval.tv_usec = 500000;&
setitimer(ITIMER_VIRTUAL, &value2, &ovalue);&
for (;;) ;&
该例子的屏幕拷贝如下:&
localhost:~$ ./timer_test&
process id is 579&
Catch a signal – SIGVTALRM&
Catch a signal – SIGALRM&
Catch a signal – SIGVTALRM&
Catch a signal – SIGVTALRM&
Catch a signal – SIGALRM&
Catch a signal –GVTALRM&
本文简单介绍了Linux下的信号,如果希望了解其他调用,请参考联机手册或其他文档。
是否原子操作?并解释为什么?
说出你所知道的&linux&系统的各类同步机制&(重点),什么是死锁?如何避免死锁(每个技术面试官必问)
死锁的条件。(&互斥条件&(&Mutualexclusion&):&1&、&资源不能被共享,只能由一个进程使用。&2&、请求与保持条件(&Hold andwait&):已经得到资源的进程可以再次申请新的资源。&3&、非剥夺条件(&Nopre-emption&):已经分配的资源不能从相应的进程中被强制地剥夺。&4&、循环等待条件(&Circularwait&):系统中若干进程组成环路,该环路中每个进程都在等待相邻进程正占用的资源。&处理死锁的策略&:&1.&忽略该问题。例如鸵鸟算法,该算法可以应用在极少发生死锁的的情况下。为什么叫鸵鸟算法呢,因为传说中鸵鸟看到危险就把头埋在地底下,可能鸵鸟觉得看不到危险也就没危险了吧。跟掩耳盗铃有点像。&2.&检测死锁并且恢复。&3.&仔细地对资源进行动态分配,以避免死锁。&4.&通过破除死锁四个必要条件之一,来防止死锁产生。&)
列举说明&linux&系统的各类异步机制
exit()&与&_exit()&的区别?
_exit终止调用进程,但不关闭文件,不清除输出缓存,也不调用出口函数。exit函数将终止调用进程。在退出程序之前,所有文件关闭,缓冲输出内容将刷新定义,并调用所有已刷新的“出口函数”(由atexit定义)。
‘exit()’与‘_exit()’有不少区别在使用‘fork()’,特别是‘vfork()’时变得很突出。
&‘exit()’与‘_exit()’的基本区别在于前一个调用实施与调用库里用户状态结构(user-mode constructs)有关的清除工作(clean-up),而且调用用户自定义的清除程序
如何实现守护进程?
守护进程(Daemon)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。守护进程是一种很有用的进程。 Linux的大多数服务器就是用守护进程实现的。比如,Internet服务器inetd,Web服务器httpd等。同时,守护进程完成许多系统任务。比如,作业规划进程crond,打印进程lpd等。
守护进程的编程本身并不复杂,复杂的是各种版本的Unix的实现机制不尽相同,造成不同 Unix环境下守护进程的编程规则并不一致。需要注意,照搬某些书上的规则(特别是BSD4.3和低版本的System V)到Linux会出现错误的。下面将给出Linux下守护进程的编程要点和详细实例。
一. 守护进程及其特性
守护进程最重要的特性是后台运行。在这一点上DOS下的常驻内存程序TSR与之相似。其次,守护进程必须与其运行前的环境隔离开来。这些环境包括未关闭的文件描述符,控制终端,会话和进程组,工作目录以及文件创建掩模等。这些环境通常是守护进程从执行它的父进程(特别是shell)中继承下来的。最后,守护进程的启动方式有其特殊之处。它可以在Linux系统启动时从启动脚本/etc/rc.d中启动,可以由作业规划进程crond启动,还可以由用户终端(shell)执行。
总之,除开这些特殊性以外,守护进程与普通进程基本上没有什么区别。因此,编写守护进程实际上是把一个普通进程按照上述的守护进程的特性改造成为守护进程。如果对进程有比较深入的认识就更容易理解和编程了。
二. 守护进程的编程要点
前面讲过,不同Unix环境下守护进程的编程规则并不一致。所幸的是守护进程的编程原则其实都一样,区别在于具体的实现细节不同。这个原则就是要满足守护进程的特性。同时,Linux是基于Syetem V的SVR4并遵循Posix标准,实现起来与BSD4相比更方便。编程要点如下;
1. 在后台运行。
为避免挂起控制终端将Daemon放入后台执行。方法是在进程中调用fork使父进程终止,让Daemon在子进程中后台执行。
if(pid=fork())&
exit(0); //是父进程,结束父进程,子进程继续&
2. 脱离控制终端,登录会话和进程组
有必要先介绍一下Linux中的进程与控制终端,登录会话和进程组之间的关系:进程属于一个进程组,进程组号(GID)就是进程组长的进程号(PID)。登录会话可以包含多个进程组。这些进程组共享一个控制终端。这个控制终端通常是创建进程的登录终端。控制终端,登录会话和进程组通常是从父进程继承下来的。我们的目的就是要摆脱它们,使之不受它们的影响。方法是在第1点的基础上,调用setsid()使进程成为会话组长:
说明:当进程是会话组长时setsid()调用失败。但第一点已经保证进程不是会话组长。setsid()调用成功后,进程成为新的会话组长和新的进程组长,并与原来的登录会话和进程组脱离。由于会话过程对控制终端的独占性,进程同时与控制终端脱离。
3. 禁止进程重新打开控制终端
现在,进程已经成为无终端的会话组长。但它可以重新申请打开一个控制终端。可以通过使进程不再成为会话组长来禁止进程重新打开控制终端:
if(pid=fork()) exit(0); //结束第一子进程,第二子进程继续(第二子进程不再是会话组长)
4. 关闭打开的文件描述符
进程从创建它的父进程那里继承了打开的文件描述符。如不关闭,将会浪费系统资源,造成进程所在的文件系统无法卸下以及引起无法预料的错误。按如下方法关闭它们:
for(i=0;i 关闭打开的文件描述符close(i);&
5. 改变当前工作目录
进程活动时,其工作目录所在的文件系统不能卸下。一般需要将工作目录改变到根目录。对于需要转储核心,写运行日志的进程将工作目录改变到特定目录如 /tmpchdir(&/&)
6. 重设文件创建掩模
进程从创建它的父进程那里继承了文件创建掩模。它可能修改守护进程所创建的文件的存取位。为防止这一点,将文件创建掩模清除:umask(0);
7. 处理SIGCHLD信号
处理SIGCHLD信号并不是必须的。但对于某些进程,特别是服务器进程往往在请求到来时生成子进程处理请求。如果父进程不等待子进程结束,子进程将成为僵尸进程(zombie)从而占用系统资源。如果父进程等待子进程结束,将增加父进程的负担,影响服务器进程的并发性能。在Linux下可以简单地将 SIGCHLD信号的操作设为SIG_IGN。
signal(SIGCHLD,SIG_IGN);
这样,内核在子进程结束时不会产生僵尸进程。这一点与BSD4不同,BSD4下必须显式等待子进程结束才能释放僵尸进程。
三. 守护进程实例
守护进程实例包括两部分:主程序test.c和初始化程序init.c。主程序每隔一分钟向/tmp目录中的日志test.log报告运行状态。初始化程序中的init_daemon函数负责生成守护进程。读者可以利用init_daemon函数生成自己的守护进程。
linux&的内存管理机制是什么?
Linux&虚拟内存的实现需要&6&种机制的支持:地址映射机制、内存分配回收机制、缓存和刷新机制、请求页机制、交换机制和内存共享机制
内存管理程序通过映射机制把用户程序的逻辑地址映射到物理地址。当用户程序运行时,如果发现程序中要用的虚地址没有对应的物理内存,就发出了请求页要求。如果有空闲的内存可供分配,就请求分配内存&(&于是用到了内存的分配和回收&)&,并把正在使用的物理页记录在缓存中&(&使用了缓存机制&)&。如果没有足够的内存可供分配,那么就调用交换机制;腾出一部分内存。另外,在地址映射中要通过&TLB(&翻译后援存储器&)&来寻找物理页;交换机制中也要用到交换缓存,并且把物理页内容交换到交换文件中,也要修改页表来映射文件地址。
linux&的任务调度机制是什么?
在每个进程的&task_struct&结构中有以下四&项:&policy&、&priority&、&counter&、&rt_priority&。这四项是选择进程的依据。其中,&policy&是进程的调度策略,用来区分&实时进程和普通进程,实时进程优先于普通进程运行;&priority&是进程&(&包括实时和普通&)&的静态优先级;&counter&是进程剩余的时间片,它的起始&值就是&priority&的值;由于&counter在后面计算一个处于可运行状态的进程值得运行的程度&goodness&时起重要作用,因此,&counter&也可以看作是进程的动态优先级。&rt_priority&是实时进程特有的,用于实时进程间的选择。&用函数&goodness()&来衡量一个处于可运行状态的进程值得运行的程度。该函数综合了以上提到的四项,还结合了一些其他的因素,给每个处于&可运行状态的进程赋予一个权值&(weight)&,调度程序以这个权值作为选择进程的唯一依据。关于&goodness()&的情况在后面将会详细分析。
五种I/O&模式——
阻塞(&默认IO模式),
非阻塞(&常用于管道),
I/O&多路复用(IO&多路复用的应用场景),
信号I/O&,
异步I/O&&&
五种&I/O&模式:&【&1&】&&&&&&&&&阻塞&I/O&&&&&&&&&}

我要回帖

更多关于 男朋友问我为什么爱他 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信