linux不能运行程序是被加密了。要保证你安装的是正确的,接着保证你的这个可执行文件有当前登录账号的执行权限,可以用lsal查看一下。
Linux系统下,程序从安全的角度来考虑,是不允许以root用户来启动的,这类程序一般会开放一个或多个端口,和其它程序或者外界进行数据交换,或者其本身就存储着重要数据,比如MySQL。一但被攻破,入侵者会获得root权限,从而掌握整个系统的所有权。
linux命令介绍
linux命令是对Linux系统进行管理的命令。对于Linux系统来说,无论是中央处理器、内存、磁盘驱动器、键盘、鼠标,还是用户等都是文件,Linux系统管理的命令是它正常运行的核心,与之前的DOS命令类似。linux命令在系统中有两种类型,内置Shell命令和Linux命令。
首先介绍一个名词控制台console,它就是我们通常见到的使用字符 *** 作界面的人机接口,例如dos。我们说控制台命令,就是指通过字符界面输入的可以 *** 作系统的命令,例如dos命令就是控制台命令。我们要了解的是基于Linux *** 作系统的基本控制台命令。
有一点一定要注意,和dos命令不同的是,Linux的命令也包括文件名等等对大小写是敏感的,也就是说,如果你输入的命令大小写不对的话,系统是不会做出你期望的响应的。
先说是不是,再问为什么。
我就知道有人会这么说,然而那样就成了一篇议论文了,而我只是想写一篇随笔。所以,不管事实是不是那样,反正我就是觉得Windows,MacOS,iOS都很流畅,而Linux,Android却很卡。当然了,这里说的是GUI,如果考量点换成是Web服务的吞吐和时延,那估计结论要反过来了,不过那是客户端程序感觉到的事,作为人,who cares!
我写这篇文章还有一个意思,那就是想牵引一个话题,如果我们想把Linux,Android(当然,Android内核也是Linux)优化到GUI不再卡顿,我们应该怎么做。
大概是去年,一个炎热的午后,吃过午饭我和同事们在公司附近晃悠,就讨论 “为什么苹果手机就不卡,安卓手机不管多贵都很卡。” 记得一位同事说,iOS在GUI方面做了很多的优化,而Android却没有。
这话说对了!不过更为重要的一点是, 不谈具体场景谈优化,都是瞎折腾!
Windows也好,iOS也好,都知道自己的应用场景,因此针对自己的应用场景做了优化之后,妥妥在自己拿手的场景下甩Linux在该场景下的表现几条街了。
下面开始正式的技术层面的分析之前,先声明几点:
1本文并不是在说Linux系统总体上很卡顿,而只是说Linux系统桌面版的GUI程序相比Winddows很卡顿,如果真觉得本文是在喷Linux,那就当是喷Linux桌面的吧。
2本文不准备讨论X window和Windows窗口子系统一个在用户态一个在内核之间的差异,这无关紧要。我的想法是,即便是你将X window扔进内核,现有的Linux内核处理GUI,该卡顿还是卡顿。
3本文仅从调度算法的角度来评价为什么Windows/iOS不卡顿而Linux却卡顿,当然还有别的视角,但并不是本文主题。
4Windows内核调度的线程而不是进程,但是本文统一采用进程这个术语,没有别的原因,只是因为进程的概念是和现代 *** 作系统概念相始终的,而线程是后来的概念。
先看服务对象
# 仅此就将Windows,MacOS/iOS和Linux的使用场景区分开来:
Windows/MacOS/iOS系统,主要是被人 *** 作,用来提供写文档,游戏,做报表,画图,上网浏览,视频播放等服务。
Linux系统,主要提供网络服务,用来支撑各种远程的客户端,为其提供数据处理和查询,数据生成,数据存储等服务。
事实证明,Linux在其专业的领域已经做的足够好,但是问题是,为什么它在GUI处理方面却总是一直很糟糕呢?这就要看具体场景的差异了。
对于网络服务而言,其场景的行为是 可预期的 ,我们可以将这些场景简单归结为:
公平快速处理网络并发请求。
公平快速处理并发磁盘IO。
高吞吐CPU密集型数据处理与计算。
Linux优秀的O(1) O(1)O(1)调度器以及后来的CFS调度器可以非常完美的cover上述三个场景,至于说为什么,不必多说,简单归纳如下:
无论是O(1) O(1)O(1)的基于优先级的时间片轮转还是CFS的基于权重的时间配额,均可以既满足优先级的差别服务需求又保证高吞吐率,这些都来自于调度器本身而不是依靠频繁的切换。
额外的简单启发式奖惩机制可以让网络IO以及磁盘IO的响应度更高,同时又不影响CPU密集型计算服务的高吞吐。
上面的第二点是一个额外的辅助,照顾IO过程快速获得响应,这是一个非常棒的辅助,但是注意,再棒的启发式算法也总是辅助性的,提高响应度就是个辅助性的锦上添花的功能,以高吞吐为目标才是根本。
IO过程对于一台Linux服务器而言是与外界交互的唯一渠道,通过该渠道可以将处理好的数据送出到网络或者磁盘,同时从网络或者磁盘获取新的数据,换句话说, IO过程类似一道门。 但也仅仅是一道门。
照顾IO过程获得高响应度这件事是为了让门开得更大,通行效率更高!
熟悉Linux内核调度器变迁的都应该知道O(1) O(1)O(1)到CFS过渡的这段历史,即260内核开始一直到2622为止的这些版本,采用Linux内核划时代的O(1) O(1)O(1)调度器,随后由于两个原因:
1、O(1) O(1)O(1)调度器动态范围太大或者太小。
2、IO补偿机制不到位,时间片分配不公平。
为了解决这些问题,Linux内核切换到了CFS调度器。
切换到了CFS调度器,事实上,人们更多指望的是CFS能够让进程时间片分配更加公平,多个进程运行更加平滑,如此一来,上GUI界面的话,岂不是就不卡顿了。
然而还是卡顿,本质原因是,场景根本就不对路子。
在Linux服务器的场景中,优先级和时间片是正相关的,无论是O(1) O(1)O(1)调度器的静态线性映射的时间片,还是CFS的动态时间配额,都是优先级越高的进程其每次运行的时间也就越久,但是实际上,这两者并不是一回事。
在更复杂的场景中,正确的做法应该是参考 时间管理的四象限法则 来设计进程调度器。其中:
优先级表示紧急性。
时间片表示重要性。
于是,如果不是因为Linux服务器场景过于单一简单,CPU的时间管理要复杂得多,比如调度器应该按照四象限法则设计成下面的样子:
1、处理重要且紧急事件的进程,需要赋予高优先级分配长时间片去抢占当前进程。
2、处理重要但是不紧急事件的进程,保持固有优先级分配长时间片就绪等待。
3、处理不重要但紧急事件的进程,提升优先级但不分配长时间片,处理完毕立即返回固有优先级。
4、既不重要也不紧急的后台进程,低优先级短时间片,系统闲了再调度。
后面我们会看到,Windows的调度器就是这般设计的。
我们先总体看看GUI系统的场景。
它的服务对象是人,和Linux的服务场景的行为可预期相反,人的 *** 作是 不可预期 的!
Windows,MacOS/iOS这种Desktop系统的GUI进程,很多时候都是在等待人的进一步 *** 作而睡眠,要么在等鼠标,要么在等键盘,要么在等声卡,显卡的输出,或者就是在将用户输入的信息往磁盘里写而等待IO完成,Desktop系统更多关注的是要对以上这些事件提供高效率的响应服务,而不是系统的数据吞吐。
Desktop在乎的是时延,而不是总吞吐,同时,这个时延还是区分对待的,有些时延的可容忍区间很大,比如网卡(网卡IO之所以优先级提升并不是很多,是因为首先网卡是有队列缓存的,而大多数的报文都是burst而来的,队列缓存可以平滑掉首包延迟,其次,由于光速极限,相比于网络延迟,主机调度延迟真的可以忽略不计。),有些却很小,比如键盘鼠标。所以说,Windows之类的Desktop系统 必须能够区分一个进程当前的紧急性和重要性。
# Linux内核能做到这种区分吗?
Linux可以通过计算一个进程的平均睡眠时间判定它是不是一个交互式IO进程,从而决定要不是给它一定的优先级提升,但是也仅能做到这个地步,因为Linux内核无法得到更进一步的信息。
Linux内核不知道一个进程到底是不是IO进程还是说仅仅在一个时间段内有IO行为的CPU密集型进程,Linux内核也不知道一个进程被唤醒是因为键盘的数据到了,还是无关紧要的信号到了,所以这一切,Linux内核只能 启发式预测。
Linux内核仅仅跟踪一个睡眠时间而且还是平均的睡眠时间,是区别不出进程当前的紧急性和重要性的。没有外界的信息输入,仅靠启发预测,当前的AI算法貌似还没有到这个境界吧。换句话说,启发算法是不准确的。你看看Linux内核O(1) O(1)O(1)调度器的sleep_avg是如何计算并如何参与动态优先级调整的,就会明白我上面说的意思。
既然Windows系统的GUI *** 作比Linux流畅,那么想必Windows肯定是做到了进程当前的紧急性和重要性的区分咯?那是当然。它是如何做到的呢?
虽然Windows的调度器也是基于优先级的,也是抢占式的,也是同优先级轮转的,这看起来和Linux并没有什么区别,甚至从43BSD开始,几乎所有的 *** 作系统的调度器基本都是按这个思路设计出来的,仅仅从 如何选出下一个投入运行的进程 这个算法上看,几乎所有的 *** 作系统调度器都是一样的。Windows与众不同的原因在于 其对优先级的不同处理方式。
自43BSD以来,所有的基于优先级的抢占式调度器的优先级计算都包括两部分因子,即固有优先级和动态优先级:
一直以来,
只是起到了 微调 的作用,而
才更具有参考意义,其比重更大。
Windows与众不同,其弱化了进程(其实应该是线程,但是我就统一写成进程吧,为了照顾不懂Windows内核原理的读者)的初始基优先级
,而强化了动态优先级
,更重要的是,动态优先级的值并非来自预测,而是来自于 事件 ,事件本身的紧急性反馈到了动态优先级的值,而事件本身的重要性则反馈到了时间片:
可以看出,Windows对于不同的事件定义了不同的优先级提升的具体数值, 将动态优先级的值和具体的事件做了精确的关联。
这些数值的定义上,甚至精细而贴心,详细的数值参见ntddkh:
//
// Priority increment definitions The comment for each definition gives
// the names of the system services that use the definition when satisfying
// a wait
//
//
// Priority increment used when satisfying a wait on an executive event
// (NtPulseEvent and NtSetEvent)
//
#define EVENT_INCREMENT 1
//
// Priority increment when no I/O has been done This is used by device
// and file system drivers when completing an IRP (IoCompleteRequest)
//
#define IO_NO_INCREMENT 0
//
// Priority increment for completing CD-ROM I/O This is used by CD-ROM device
// and file system drivers when completing an IRP (IoCompleteRequest)
//
#define IO_CD_ROM_INCREMENT 1
//
// Priority increment for completing disk I/O This is used by disk device
// and file system drivers when completing an IRP (IoCompleteRequest)
//
#define IO_DISK_INCREMENT 1
//
// Priority increment for completing keyboard I/O This is used by keyboard
// device drivers when completing an IRP (IoCompleteRequest)
//
#define IO_KEYBOARD_INCREMENT 6
//
// Priority increment for completing mailslot I/O This is used by the mail-
// slot file system driver when completing an IRP (IoCompleteRequest)
//
#define IO_MAILSLOT_INCREMENT 2
//
// Priority increment for completing mouse I/O This is used by mouse device
// drivers when completing an IRP (IoCompleteRequest)
//
#define IO_MOUSE_INCREMENT 6
//
// Priority increment for completing named pipe I/O This is used by the
// named pipe file system driver when completing an IRP (IoCompleteRequest)
//
#define IO_NAMED_PIPE_INCREMENT 2
//
// Priority increment for completing network I/O This is used by network
// device and network file system drivers when completing an IRP
// (IoCompleteRequest)
//
// 网卡IO之所以优先级提升并不是很多,是因为首先网卡是有队列缓存的,而大多数的报文都是burst而来的,队列缓存可以平滑掉首包延迟,其次,由于光速极限,相比于网络延迟,主机调度延迟真的可以忽略不计。
#define IO_NETWORK_INCREMENT 2
//
// Priority increment for completing parallel I/O This is used by parallel
// device drivers when completing an IRP (IoCompleteRequest)
//
#define IO_PARALLEL_INCREMENT 1
//
// Priority increment for completing serial I/O This is used by serial device
// drivers when completing an IRP (IoCompleteRequest)
//
#define IO_SERIAL_INCREMENT 2
//
// Priority increment for completing sound I/O This is used by sound device
// drivers when completing an IRP (IoCompleteRequest)
//
#define IO_SOUND_INCREMENT 8
//
// Priority increment for completing video I/O This is used by video device
// drivers when completing an IRP (IoCompleteRequest)
//
#define IO_VIDEO_INCREMENT 1
//
// Priority increment used when satisfying a wait on an executive semaphore
// (NtReleaseSemaphore)
//
#define SEMAPHORE_INCREMENT 1
---------------------
仔细看,你会注意到对于声卡而言,其IO完成时,优先级提升会很大,而磁盘,显卡这种却并不是很多,这充分体现了设计者的贴心。这充分考虑到了人耳的灵敏度和人眼的分辨率之间的对比,声音是作为流顺序输出的,耳朵很容易分辨出声音的卡顿,而对于图像而言,完全可以慢慢双缓冲刷层,人眼相比之下没有那么高的分辨率识别到,因此声卡事件必须优先处理。
同时,对于磁盘,网卡之类的,人就更是感觉不到了。除了声卡之外,键盘鼠标 *** 作的IO完成对于优先级提升的数值也很可观,因为键盘鼠标如果卡顿,人的输入会明显感觉到延迟,鼠标则显拖沓,这都是很容易识别的卡顿事件,所以Windows给予了进程更高的动态优先级来尽快处理这些事件。
对于窗口子系统而言,当一个窗口获得焦点时,对应的处理进程的优先级也会得到提升,这会给人一种 你 *** 作的界面总是很流畅 的感觉,毕竟你 *** 作的界面就是前台窗口,至于说此时后台窗口的处理进程,即便是僵死了你也不会有感觉,因为你并不 *** 作它们呀,当你 *** 作它们时,对应的处理进程的优先级就会提升。
所有的优先级提升都伴随着时间片的重新计算,但是和Linux不同的是,Windows并没有直接将进程优先级和时间片按照正相关关联起来,时间片是独立计算的,大多数时候,Windows对于所有的进程,不管优先级是多少,均采用同一个时间片。
如此看来,Windows虽然也是优先级调度的系统,但是其优先级却是 *** 作行为驱动的 ,这便是其与众不同之处。
Linux内核调度系统会精细区分磁盘事件的wakeup和键盘鼠标声卡事件的wakeup吗?不会。
说完了Windows为什么 *** 作GUI会很流畅,该说点不好的了,
# Windows经常会死机,为什么呢?
这很大程度上也和上面描述的调度器有关。
仔细看这个 *** 作行为驱动的动态优先级调度器,很大的一个问题就是容易饿死低优先级的进程,特别是Pbase P_{base}P base 很低的进程。
Windows的解决方案是采用一个后台进程(学名叫做平衡集管理线程)轮询的方式,将超过秒级都没有被调度的进程的优先级拉升到很高的位置参与抢占。
这个机制有啥问题呢?问题在于Windows需要第三方线程来缓解饥饿,而不是靠调度器自身,这便增加了调解失败的可能:
第三方线程本身的问题没有按照预期工作。
饥饿进程过多。
饥饿进程优先级提升后又被抢占。
…
除了死机问题之外,Windows系统对于服务器版本的调度器调整做的也不够优雅,Windows仅仅是调整了服务器版本的系统参数,而几乎没有对调度的算法做任何修改。对于服务器版本,Windows只是将时间片延长了而已,同时几乎不再动态计算时间片,而是选择始终使用相同的一个足够长的值,以减少进程切换提高吞吐率。显然这种方式并不妥当,因为动态优先级根据事件的提升,还是会造成进程间不断抢占,从而影响吞吐。
不过,毕竟Windows是一个Desktop系统,本身就不是为高吞吐而生的,这种针对服务器版本的策略调整便是无可厚非了。正如Linux服务器虽然可以很完美应对高吞吐场景,其Desktop版本比如Ubuntu,Suse不也是心有余而力不足吗?虽然Linux内核也有动态优先级提升这一说。
# 该简单总结一下了。
在人机关联上,Windows更加靠近人这一端,适应了人的 *** 作行为,为 *** 作该机器的人提供了良好的短时延体验,Linux相反,它靠近机器一端,让CPU可以尽可能开足马力跑task而不是频繁切换,从而为客户端提供最大的数据吞吐。
Windows的设计甚是精妙,考虑到了人的行为的每一个细节(除了对于死机的耐受力),除了动态优先级和具体时间精确关联之外,对于待机恢复时间deadline在7秒内也是很值得拍案,这个7秒的阈值考虑到了人的短期记忆的极限,如果有人突然想到了一个点子,需要打开电脑将其记录下来,那么打开电脑的时间如果超过了7秒,那么可能这个点子就溜走了,所以待机恢复时间必须限制在7秒以内,哇塞不哇塞。
对于MacOS/iOS没有过多的研究,但是可以想见应该也如Windows这般了。因为它们都处在人机关联的人的这一端。随便看了下MacOS的开发手册,找到了下面的段落:
当我找和GUI和调度相关的东西时,就在上面这段的下面,有这个定义:
嗯,看来内核也是能看到所谓的前台窗口的。
不管怎么说,Windows,MacOS/iOS这些系统,共同的特点就是 大多数情况下,同时只有一个焦点窗口在前端接受输入输出。 毕竟把窗口缩小排满一屏幕的很少见。然后呢?然后这就是一个典型的场景啊!
你看看Win10,不就可以设置为平板模式吗?
倾其机器和 *** 作系统内核所有资源和机制照顾这少数的,几乎是唯一的前台焦点窗口的处理进程,这几乎就是单进程处理啊! 然后处理好用户的窗口切换即可,比如Windows的Ctrl-Tab。
Linux如若按照这个思路,单独再写一个调度器,替换掉CFS,而不是增加一个调度类,如此一来将系统中所有的进程统一按照 优先级和事件相关联 的方式对待,我想问题应该能优化不少。
已经快凌晨了,说点别的但是相关的吧。
Linux内核O(1) O(1)O(1)调度器的历史其实很短暂,26初始到2622,但是非常经典的Linux内核方面的书,都是在描述这期间的Linux内核版本,这在当时就给了人们一个假象,O(1) O(1)O(1)调度器是无敌的,是划时代的,于是,当有了新的CFS调度器的时候,人们哇塞一声,O(1) O(1)O(1)只是银河系级别的,而CFS是宇宙级别的。
但其实,O(1) O(1)O(1)的意义只是优化了 如何快速找到下一个要运行的进程 ,虽然它也涉及了动态优先级的计算,但是这并不是它的重点。说实话,你若看看Windows的调度器,44BSD,SystemV4的调度器,基本上都是位图加优先级队列的形式,思路几乎是同一个,这么说来都是O(1) O(1)O(1)咯,而且人家这些调度器早在Linux还是O(n) O(n)O(n)调度器的时候就已经存在好几年了,却无人问津。
Windows内核的调度算法不为人知的原因除了其闭源之外,还有一个原因就是Windows内核方面的技术总体上推广的人太少,国内除了潘爱民一直在致力于这方面的推广之外,在没有别人了。估计是因为大家觉得Windows内核方面,Debug之外的东西,学了也没啥用吧。
你说Linux开源没错,BSD不也开源吗?怎么就没有人注意BSD的调度器实现呢?哈哈,开不开源无所谓,关键得能造势搞事情,而且获取方便,让大家用起来你的东西才真真的啊。Linux24版本说实话及其垃圾,但关键是很多人用起来了,这就是全部了。Solaris虽然设计完美优雅,可是有壁垒,没人用,最终也还是凉凉。同样的事情参考以太网。
通篇都在比较Windows和Linux的调度器如何影响人们的 *** 作体验。最后说说iOS和Android吧,题外话,不涉及技术。
Android就是卡,不接受反驳。
再贵的Android机器也卡,三星的,华为的照卡不误,只是相比别的稍微好一点点而已。这意味着它们成不了街机。因为手机是买来用的,不是买来debug的,除了程序员没人在乎Android机慢的原因,即便是程序员也很少有折腾明白的,只是因为这份职业让他不用Android就不正确。不过现在互联网公司的程序员用iPhone的也多了,因为好用啊。再者说了,互联网公司程序员大概率以做业务逻辑为主,底层技术欠缺,无力debug,当然是什么好用用什么,iPhone贵,但是互联网程序员收入高啊。
最终,Android机的唯一优势就是价格,你让Android卖的和iPhone一样贵试试,分分钟被绞杀。要说还有唯一点五的,就是品牌,XX也不是吃素的,就算XX做的再烂,就凭它这牌子,也不缺市场,比如我就是XX用户,我并不是觉得XX的Android比小米的Android好,而是我喜欢XX这个公司,这个品牌,仅此而已
1,处理机管理:linux是真正的多用户 *** 作系统,windows(楼主说的windows是哪一个?2003?XP?还是NT?)一般来讲,其实不是真正的多用户。在Linux系统中,提高处理机使用率的技术措施主要是多道和分时,处理机在进程之间切换,按照一定的规则轮流执行每个进程。对于单个处理机的系统,这些进程宏观上看似并行执行,而微观上来看仍然是串行执行的,这种执行方式被称为并发执行。 *** 作系统通过并发控制机制,对处理机进行分配、调度,在保证每个进程都得到公平合理执行的同时,使系统中的各种资源得到充分的使用。不过我们得明白一点,linux其实不是完整的 *** 作系统,只是内核。还需要shell等来组成一个可 *** 作的系统。
2,设备管理:在linux上,一切设备都文件。大多数Linux资源都能以文件的方式来访问。无论哪种文件类型,Linux的文件抽象---也就是说,它习惯于将几乎所有的东西按文件对待---能够让你使用相同的接口打开、关闭、读取和写入不同的文件。在Linux系统中,所有设备都作为一类特别文件对待,用户像使用普通文件那样对设备进行 *** 作,从而实现设备无关性。但是,设备文件除了存放在文件I节点中的信息外,它们不包含任何数据。系统利用它们来标识各个设备驱动器,核心使用它们与硬件设备通信。有两类特别设备文件,它们对应不同类型的设备驱动器:
字符设备 最常用的设备类型,允许I/O传送任意大小的数据,取决于设备本身的容量。使用这种接口的设备包括终端、打印机及鼠标。
块设备 这类设备利用核心缓冲区的自动缓存机制,缓冲区进行I/O传送总是以1KB为单位。使用这种接口的设备包括硬盘、软盘和RAM盘。
3,文件管理:linux的文件系统毋庸置疑具备更高的效率。我的linux安装好后,就没有整理过磁盘。因为linux的ext3等文件系统本身就具备更高的执行效率甚至可以自我整理。另外linux还支持NFS网络文件系统,方便实现网络上不同 *** 作系统的高效读写。
在Linux系统中,除根目录(root)以外,所有文件和目录都包含在相应的目录文件中。Linux文件系统采用带链接的树形目录结构,即只有一个根目录(通常用“/”表示),其中含有下级子目录或文件的信息;子目录中又可含有更下级的子目录或者文件的信息。这样一层一层地延伸下去,构成一棵倒置的树。这个和win有点像。
4,进程管理:Linux用分时管理方法使所有的任务共同分享系统资源。主要有交互进程,批处理进程,监控进程等不同作用的进程类型,并且具备多中启动方式。linux具备win不具有的特点,任务抢占机制,在一些应用程序出现问题的时候可以快速的被系统取代。这都是win不具备的。
众所周知,为了保护共享数据,需要一些同步机制,如自旋锁(spinlock),读写锁(rwlock),它们使用起来非常简单,而且是一种很有效的同步机制,在UNIX系统和Linux系统中得到了广泛的使用。但是随着计算机硬件的快速发展,获得这种锁的开销相对于CPU的速度在成倍地增加,原因很简单,CPU的速度与访问内存的速度差距越来越大,而这种锁使用了原子 *** 作指令,它需要原子地访问内存,也就说获得锁的开销与访存速度相关,另外在大部分非x86架构上获取锁使用了内存栅(Memory Barrier),这会导致处理器流水线停滞或刷新,因此它的开销相对于CPU速度而言就越来越大。
在 *** 作系统中,数据一致性访问是一个非常重要的部分,通常我们可以采用锁机制实现数据的一致性访问。例如,semaphore、spinlock机制,在访问共享数据时,首先访问锁资源,在获取锁资源的前提下才能实现数据的访问。这种原理很简单,根本的思想就是在访问临界资源时,首先访问一个全局的变量(锁),通过全局变量的状态来控制线程对临界资源的访问。但是,这种思想是需要硬件支持的,硬件需要配合实现全局变量(锁)的读-修改-写,现代CPU都会提供这样的原子化指令。采用锁机制实现数据访问的一致性存在如下两个问题:
1、 效率问题。锁机制的实现需要对内存的原子化访问,这种访问 *** 作会破坏流水线 *** 作,降低了流水线效率。这是影响性能的一个因素。另外,在采用读写锁机制的情况下,写锁是排他锁,无法实现写锁与读锁的并发 *** 作,在某些应用下回降低性能。
2、 扩展性问题。当系统中CPU数量增多的时候,采用锁机制实现数据的同步访问效率偏低。并且随着CPU数量的增多,效率降低,由此可见锁机制实现的数据一致性访问扩展性差。
为了解决上述问题,Linux中引进了RCU机制。该机制在多CPU的平台上比较适用,对于读多写少的应用尤其适用。RCU的思路实际上很简单,下面对其进行描述:
1、 对于读 *** 作,可以直接对共享资源进行访问,但是前提是需要CPU支持访存 *** 作的原子化,现代CPU对这一点都做了保证。但是RCU的读 *** 作上下文是不可抢占的(这一点在下面解释),所以读访问共享资源时可以采用read_rcu_lock(),该函数的工作是停止抢占。
2、 对于写 *** 作,其需要将原来的老数据作一次备份(copy),然后对备份数据进行修改,修改完毕之后再用新数据更新老数据,更新老数据时采用了rcu_assign_pointer()宏,在该函数中首先屏障一下memory,然后修改老数据。这个 *** 作完成之后,需要进行老数据资源的回收。 *** 作线程向系统注册回收方法,等待回收。采用数据备份的方法可以实现读者与写者之间的并发 *** 作,但是不能解决多个写着之间的同步,所以当存在多个写者时,需要通过锁机制对其进行互斥,也就是在同一时刻只能存在一个写者。
3、 在RCU机制中存在一个垃圾回收的daemon,当共享资源被update之后,可以采用该daemon实现老数据资源的回收。回收时间点就是在update之前的所有的读者全部退出。由此可见写者在update之后是需要睡眠等待的,需要等待读者完成 *** 作,如果在这个时刻读者被抢占或者睡眠,那么很可能会导致系统死锁。因为此时写者在等待读者,读者被抢占或者睡眠,如果正在运行的线程需要访问读者和写者已经占用的资源,那么死锁的条件就很有可能形成了。
Linux进程调度采用的是抢占式多任务处理,所以进程之间的挂起和继续运行无需彼此之间的协作。
在一个如linux这样的多任务系统中,多个程序可能会竞争使用同一个资源,在这种情况下,我们认为,执行短期的突发性工作并暂停运行以等待输入的程序,要比持续占用处理器以进行计算或不断轮询系统以查看是否有输入到达的程序要更好。我们称表现好的程序为nice程序,而且在某种意义上,这个nice 是可以被计算出来的。 *** 作系统根据进程的nice值来决定它的优先级,一个进程的nice值默认为0并将根据这个程序的表现不断变化。长期不间断运行的程序的优先级一般会比较低。
程序占用文件步骤是:
1、只查看该进程:ps-ef|grep11345。
2、查看该进程打开的文件:lsof-p11345。
3、查看内存分配:lcat/proc/11345/maps。
4、查看堆栈:pstack11345。
5、查看发出的系统调用:strace-p11345。
6、查看调用库函数:ltrace-p11345。
以上就是关于linux ./不能运行程序 是不是被加密了全部的内容,包括:linux ./不能运行程序 是不是被加密了、为什么Windows/iOS *** 作很流畅,而Linux/Android却很卡顿呢、LINUX与WINDOW哪些功能是相似的,哪些是各自不可替代的,等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)