有一种文件系统,根本不在磁盘上。这种文件系统就是大名顶顶的ram-basedfilesystem。实际上,在Linux系统中,/dev、/proc、/sys目录里面的内容与硬盘是没有半毛钱关系的。那么这些玩意到底有什么用,怎么用,在听我白乎完以后,最好再去看看内核源代码中的一些文档。要知道文档这种东西,真正读起来就嫌少了。
至于你信不信,反正我是信了。在这一章中只是讲这些内容我是不会尽兴的,我还会追加一些譬如tmpfs、debugfs、relayfs等。虽然这似乎是一些很冷的话题,对于很多人来说,它们的受欢迎程度,肯定是既赶不上陈冠希老师的摄影作品,也赶不上苍井空老师的启蒙课程。不过人在江湖身不由己,因为工作的原因,为了提高自己抓紧升P,淘宝技术走p路线
9.1.1理解日志1.元数据电影《色戒》告诉我们,床戏是用身体来诠释爱情的;而文件系统则教导我们,元数据就是诠释数据的数据。有点绕,较为通俗的解释是这样的:作为文件系统,一定要提供存储、查询和处理数据的功能。那么,文件系统就保存了一个内部数据结构,使得这些操作成为可能。这个内部数据结构,就是元数据,它为文件系统提供特定的身份和性能特征。元数据对于99.99%的人来说,都是不必关心的,因为元数据是专门交给文件系统的驱动程序使用的,平时根本碍不着你什么事儿。不过有一点很重要:要想文件系统的驱动程序好好干活,它就得轻松愉快地找到元数据。要求有三:一要合理、二要一致、三要无干扰。否则的话,驱动程序就没法理解元数据,也操作不了,那么你就只能跟你的文件说拜拜了。这里啰嗦几句。文件系统是文件系统,文件系统的驱动程序是文件系统的驱动程序,不是一码事,就好比人是人他妈生的,妖是妖他妈生的。那些大家耳熟能详的ext2、ext3等,实际上叫文件系统类型。可以这样理解:文件系统是项目,类型是方案,驱动程序就是执行人。虽然不能混淆是非,但是平时跟大家说文件系统,上述三点一般都代表了,不必太较真儿。
2.fsck既然文件系统驱动程序那么娇贵,就得有人伺候它,给它请个保姆。这个保姆就是fsck。fsck确保文件系统驱动程序要用的元数据是干净的,但是有时候也不会特别周到。它具体是怎么伺候文件系统驱动的呢?是这样的:
每次Linux启动,在没有挂接任何文件系统的时候,都会启动fsck扫描一下/etc/fstab文件中列出的所有本地文件系统;每次Linux关闭,它要把还在内存中的被称之为页面缓存或磁盘缓存中的数据转送到磁盘,还要保证把已经挂接的文件系统卸载干净。
这套流程说简单了就是:fsck要检查那些即将被挂接的文件系统,之前是被卸载干净了的,然后做出一个合理的假设——所有元数据都是干净的,没问题。
3.fsck的问题不过话分两头说,当年陈冠希老师对自己的摄影作品也是细心呵护,珍爱有佳,可是偏偏就有意外发生。对于陈老师来说,这个意外对他本人或许还给自己“增光”不少,好多人羡慕得不得了。可是对于文件系统来说,塞翁一旦失马,马还回得来吗?一般是这样的:当Linux遇到异常关机(比如断电、kernelpanic或者管理员有点蛋疼),重启后fsck就会发现有文件系统没卸载干净,对应的元数据可能不干净,已经出了问题。于是乎开始奋力苦干,全面审查元数据,修正一切可以修复的错误,文件系统又可以正常使用了。从这点来看,似乎“马”是回来了。星星还是那颗星星,月亮还是那个月亮,可是“马”还是那匹“马”吗?前面说过,fsck是修正一切可以修复的错误,那么不能修正的怎么办呢?丢掉——这似乎很残忍,但是也只能丢掉,否则就会像手臂上化了脓的伤口,如果不切掉那块肉,以后失去的可能是整个手臂。其实还有远比这个要严重的,fsck要扫描全部元数据。这显然不是技巧活儿,是需要动蛮力的。少则花几分钟,多则几小时。如果这事儿发生在任务繁重的数据中心,标准的fsck过程就不是在帮你了,那是害你不死啊!
9.1.2ReiserFS——卓越的小文件性能与渺茫的未来说完日志,我们开始说ReiserFS。选择ReiserFS说事儿不单单是因为它是众多日志型文件系统之一,还有它的设计目的也很特别。
它的设计者HansReiser的想法是:一个最好的文件系统,不单能够管理好用户的文件,还能够适应环境干点别的,比如代替数据库。
2.ReiserFS技术ReiserFS的小文件性能如此突出,那么它是怎么练就这种绝世武功的呢?原来ReiserFS采用了一种叫做B*树的数据结构。这是一种全新的经过特殊优化的树形数据结构。ReiserFS用它来组织元数据,相当于整个磁盘分区是一个B*树(元数据和真正数据放在一起,叶子节点也放数据)。
这里说明一下B*树的概念。一般专业学过计算机应用的,多少都会接触点数据结构这个东西。不管是老师讲的,还是道听途说来的,链表、堆栈、树、图这些大体上都是了解的。作为“树”这种数据结构,书上说得最多的就是二叉树。但凡涉及二叉树,说得最多的就是二分查找,因为效率高嘛(100万个数据,只要20几次比较就能找到所要的数据)。
在二分查找领域中,利用“树”来说事儿的普遍有二叉查找树、平衡二叉查找树,乃至AVL树和红黑树!!!!!!!!!!!!!!
红黑树这里大红大紫的当推红黑树,因为C++的STL(标准模板库)中的map容器就是使用的这种数据结构(内存)。乃至后来Java中的map,苹果Objective-C中的字典也使用这种数据结构。只要你是程序员,就离不开它。因为在基于内存这种介质的二分查找算法中,红黑树是最稳定的。
B树(B树-》B+树一般文件系统-》B*树ReiserFS或数据库)
那么基于磁盘介质上的高效查找(注意这里没有说二分)算法呢?答案是B树,正如很多人了解到的“B-”树。其实世界上本没有“B-”树这个东西,只是叫的人多了,它便成为了“B-树”。究其原因是某些人翻译得不负责任,大多数外国文献中使用B-tree来说明,就翻译成“B-树”了。
不过我一向不喜欢把话说死,其实ReiserFS的尾文件压缩是以牺牲速度为代价的。有鉴于这个原因,ReiserFS的作者们提供了一个开关,可以让管理员关掉尾文件压缩功能,可以让管理员根据实际使用情况,酌情考虑是要速度还是存储能力。
3.渺茫的未来对于大多数男人是只知道女人的底裤在那里,却不知道女人的底线在哪里,总是想挑战女人的极限;对于我们德高望重的HansReiser应该取反,因为他的女人一直在挑战他的极限,结果……耗子急了咬了猫。2008年4月28日,被加利福尼亚州奥克兰法庭认定其杀妻罪名成立,判决15年监禁。从此ReiserFS的开发就基本处于停滞状态。虽然有开发者主动挺身而出,但是主创灵魂已身陷囹圄,ReiserFS的命运一直蒙着一层阴影。乃至一度大力推广ReiserFS的Novell公司都开始反水,在2006年10月12日宣布在未来的SUSELinuxEnterprise版本中不再使用ReiserFS作为默认文件系统,改用ext3。即便如此,ReiserFS依然是Linux系统中最优秀的文件系统之一,而且现在依然是可以使用的。
9.1.3应用实战到目前为止,Linux的主线版本已经升级到了3.8,但是很不幸的是,由于ReiserFSv4一直没有被纳入Linux的主线,我们不得不通过内核补丁来一尝ReiserFSv4的朱唇,到本书截稿之前支持的最高内核版本是3.7。要使用ReiserFSv4还是有点小麻烦的,具体步骤是这样的:1.准备内核源代码。这年头怎么都得是2.6.xx的吧?2.下载一个对应您内核版本的补丁。reiser4-for-2.6.xx.patch.gz。3.下载ReiserFSv4的工具包。libaal-1.0.5.tar.gz和reiser4progs-1.0.6.tar.gz。4.安装libaal。一个工具库,提供个哈希表,位操作什么的。5.安装reiser4progs。这是用来使用ReiserFS分区的工具。包括debugfs.reiser4、fsck.reiser4、measurefs.reiser4和mkfs.reiser4。debugfs.reiser4用来调试ReiserFS的,这个工具利用了我们后面要讲解的debugfs;fsck.reiser4用来检测和修复ReiserFS磁盘分区的,fsck我们前面已经介绍过了;measurefs.reiser4用于度量ReiserFS磁盘分区,比如查看磁盘碎片;mkfs.reiser4就是格式化工具了。6.给内核源代码打补丁。一般执行的操作就是:
gzip-cd../reiser4-for-2.6.xx.patch.gz|patch-p1注意:执行这步操作要确保你在内核源代码的根目录下。7.配置、编译和安装内核。8.使用新内核重新启动。重新启动后,你就拥有ReiserFS了。接下来要做的就是找一个分区,使用mkfs.reiser4进行格式化,使用mount命令挂载就好了。9.1.4小结我讲这些并不是想让大家如何深刻的理解日志、ReiserFS乃至什么B*树。就好比女人如画,不同的画中有不同的风景,Linux也是如此,左看右看上看下看,角度不同,风景各异。再一次重复之前说的话:用以前完全不可能的方法来完成事情。日志和ReiserFS不正是对这句话很好的诠释吗?
pwd/boot/grub#lltotal284-rw-r--r--.1rootroot63Jul102015device.map-rw-r--r--.1rootroot13396Jul102015e2fs_stage1_5-rw-r--r--.1rootroot12636Jul102015fat_stage1_5-rw-r--r--.1rootroot11780Jul102015ffs_stage1_5-rw-------1rootroot926Dec3114:49grub.conf-rw-r--r--.1rootroot11772Jul102015iso9660_stage1_5-rw-r--r--.1rootroot13284Jul102015jfs_stage1_5lrwxrwxrwx.1rootroot11Jul102015menu.lst->./grub.conf-rw-r--r--.1rootroot11972Jul102015minix_stage1_5-rw-r--r--.1rootroot14428Jul102015reiserfs_stage1_5-rw-r--r--.1rootroot1341Nov152010splash.xpm.gz-rw-r--r--.1rootroot512Jul102015stage1-rw-r--r--.1rootroot126116Jul102015stage2-rw-r--r--.1rootroot12040Jul102015ufs2_stage1_5-rw-r--r--.1rootroot11380Jul102015vstafs_stage1_5-rw-r--r--.1rootroot13980Jul102015xfs_stage1_5
进程文件系统procfs
procfs之于Linux的重要程度就好比眼睛之于心。眼睛是心灵的窗口,直达心底;眼睛是心灵感知世界的大门,洞悉全局;眼睛是人与人之间心灵沟通的桥梁,展现彼此。procfs是进程文件系统的缩写。这是一个伪文件系统(启动时动态生成的文件系统),用于用户空间通过内核访问进程信息。但是经过不断的演进,如今Linux提供的procfs已经不单单用于访问进程信息,还是一个用户空间与内核交换数据修改系统行为的接口。这个文件系统通常被挂接到/proc目录。procfs并不是Linux的原创,它源自于UNIX世界,现在世上几乎所有类UNIX系统都提供。可能是历史太过悠久,如今好多人开始讨厌它,排挤它,发明了如sysfs这样的东西想要替代它。由于FreeBSD已经放弃了procfs,它默默的承受着:早就说分手,从未被遗弃的命运。因为procfs就像气质非凡的美女,虽然朱颜老去,但内在的神韵一直吸引着我们,无法抗拒。9.2.1神秘的9号计划procfs最早在UNIX第8版实现,后来又移植到了SVR4,最后由一个被称为“9号计划”的项目做了大量改进,使得/proc成为文件系统真正的一部分。
“9号计划”是贝尔实验室创造的另外一个操作系统。这是一个“高尚”的操作系统,一个“纯粹”的操作系统,一个“有道德”的操作系统,一个“脱离了低级趣味”的操作系统,一个“有益于人民”的操作系统。很久很久以前,贝尔实验室的一群人创造了至今最为重要的网络操作系统——UNIX。曾经有人说过:即便这是贝尔实验室做出的唯一贡献,那也足以让它名垂千古了!到20世纪80年代中期,计算的趋势从大的集中式的分时计算向更小的个人机器组成的网络方向转移。人们早已厌倦了既受管束又超载的分时机器,极其渴望使用一种小巧而又自由的系统,缺点就是有点慢。随着微型计算机越来越快,唯一的缺点也可以无视了,于是这种计算方式一直延续到了现在。UNIX是一个古老的分时系统,很难适应这种计算方式。即便可以让UNIX支持图形和网络功能,但办法有点糟,很难管理。更要命的是,这种集中到分散的转化无法做到无缝过度,因为分时是专政和资源集中化,个人计算是民主和资源分散化,而且是从根本上扩大了管理问题。于是,有一些愤青(包括DennisRitchie和KenThompson),决心依靠自己的经验,超越UNIX,编写出最完美的操作系统,这就是他们的“9号计划”。
9.2.2/proc目录如今的/proc目录已经变得很复杂很复杂,这也是开始排挤它、讨厌它、找人替代它的一个主要出发点。因为如今的procfs已经无法满足UNIX的KISS文化中简单这一条了。但是由于历史原因,至今也无法找到一个更好的办法来完全替代它。那么既然无法反抗,就只能默默享受吧。大多数情况下,你在/proc目录下能够看到的文件差不多就是
表9-1所列出的这些:
除了可能会有这些文件外,/proc目录下还有好多目录。大多数系统会有表9-2所列出的这些目录内容:表9-2/proc目录下的子目录
这里很重要的是[number]这些目录,每个进程一个目录,目录名就是进程ID。里面包含了一些文件,这些文件描述着一个进程的方方面面,这是procfs最初目的的体现。这些文件都是只读的,你不能修改,仅用于获得系统中进程的运行信息。典型的工具如top、ps等,就是依据这些目录中的文件所提供的内容进行工作的。
这里有一个特别的目录就是sys目录,它所包含的文件大多是可以写的,通过改写这些文件的内容,可以起到修改内核参数的目的。实际上系统命令sysctl就是利用这个目录实现的全部功能。使用C语言编程时,系统调用的sysctl是这个接口的封装。
中断被划分成不同的等级,高级别的中断可以被CPU优先照顾,同等级别的中断就按照先后顺序排队处理,这在系统内部被称为中断请求队列。高级别中断相对于低阶别中断就有了一种特权。
随着时代的变迁,单一CPU的设计遇到了瓶颈,无法再继续提高运算能力,计算机开始朝着多核和多CPU方向发展。当前主流的服务器配置都可以达到4CPU16核心。在这种情况下,相对于数量没有太多变化的外部设备来讲,CPU不算是一种稀缺资源,但是
如何合理的将来自不同设备的中断请求划分给不同的CPU就成了一个新的问题。由此引入了一个新的概念,中断平衡。有了中断平衡,我们就又引入了一个新的特权,中断的CPU独享特权。
即可以指定某颗具体的CPU或CPU的某颗核心专门处理某个或某些中断请求。
大多数的主流Linux发行版都有一个默认的中断平衡策略。但是这些默认的中断平衡策略并不一定能够满足某个特定系统的性能需求,比如一个有着非常繁重的网络资源请求的系统。默认的策略是,网卡的中断请求在多CPU环境下,仅发给CPU0。在一些特定情况下,会导致CPU0的资源占用率达到了100%,而其他CPU资源占用却只有1%~2%,甚至是0%。由于CPU0也要负责任务调度,那么遇到这种情况下,系统基本上就处于死机状态,无法继续正常工作了。
解决的办法就是,让网卡把中断请求发给其他CPU,不过这也需要网卡配合才行,幸好现在大多数服务器所配备的网卡具备这个能力。
那么该如何操作呢?这里先要引入一个概念——中断的CPU亲缘性,即中断与哪些CPU亲缘。设置好中断的CPU亲缘关系,就可以让中断只发往那些它所亲缘的CPU。
在进行这个设置之前,我们首先要搞清楚,我们的物理设备,到底使用的是哪个中断,每个中断有一个唯一的编号,我们要找到这个编号。可以通过procfs的/proc/interrupt文件来获得。这个文件中的内容差不多是这样的:
CPU0CPU10:340IO-APIC-edgetimer1:34350IO-APIC-edgei80426:30IO-APIC-edgefloppy8:00IO-APIC-edgertc09:376140IO-APIC-fasteoiacpi12:121390IO-APIC-edgei804214:00IO-APIC-edgeata_piix15:00IO-APIC-edgeata_piix16:303170IO-APIC-fasteoiahci17:33250IO-APIC-fasteoi82801BA-ICH218:450IO-APIC-fasteoiuhci_hcd:usb219:00IO-APIC-fasteoiehci_hcd:usb121:932530IO-APIC-fasteoiprl_vtg22:260IO-APIC-fasteoiprl_tg23:32590IO-APIC-fasteoieth0
文件的第一列就是中断号,第二列和第三列是所对应的CPU接收到的该中断的数量,最后一列则代表使用该中断的设备,至于倒数第二列,我们不用关心它。从这个例子中网卡,即eth0使用了23号中断。而且很明显的是只有CPU0接收到了中断,CPU1没有接到过。
#pwd/proc/irq/8#catsmp_affinity1#只由CPU0处理如果改为1111表示4个CPU都会参与中断处理
找到了对应的中断号,我们可以开始设置它的CPU亲缘性了,具体的是设置procfs的/proc/irq/[num]/smp_affinity文件的内容。
#ls-ld/vardrwxr-xr-x.20rootroot4096Feb1220:30/var#ls-ld/etcdrwxr-xr-x.73rootroot4096Feb2415:11/etc
方法一,使用相对路径。采用相对路径是比较容易也很容易想到的一种方法。通常情况下程序工作的也很好,调试起来也不会有问题。不过当程序投入使用后,会发现一个问题就是:要想正确执行这个程序,就必须进入这个程序所在的目录才行,否则就会找不到配置文件或者日志文件输出路径不对。想让自己的程序成为一个顺手工具,在任意路径下都能正确执行的希望就此破灭。究其原因是因为fopen、open等这些打开文件的函数或系统调用在使用相对路径时,默认的当前路径是程序的执行路径,而不是程序所在的路径。换句话说,你在什么路径下执行这个程序,那么相对路径就是相对于你当前所在的这个路径的。所以自然就会出问题了。可见,这种方法不是一个好方法。
需要注意的是,你的程序如果是基于多进程方式,并且是采用Linux守护进程模式运行的,那么一定要在主进程或调用daemon之前完成上述操作,否则将无法获得这个绝对路径。因为对于一个已经丧失亲生父母的孤儿来说,继父无法提供体贴入微的关怀,它的身心怎么会健全呢?
我的步骤
syncecho3>/proc/sys/vm/drop_cachesswapoff-aswapon-a好了,这就操作完成了。再次使用free命令查看内存,会发现剩余内存已经具有惊人的数量了。于是内存真的没有问题了,一等奖金我们拿到了。不过这个故事没有完。因为故障率就是没有降下来。用户还在抱怨,新业务无法拓展。不过有一个好的消息是,经过这么一折腾,上头居然批准了新设备采购计划。直到新设备上架之后,故障率才显著降低。不过这还不是这个实战的终结。其实这是一个伪命题!在Linux中,这种手工释放内存的方式是根本解决不了什么内存泄漏问题的,而且还会严重影响系统性能。这是为什么呢?我先来解释一下这三个步骤的作用:第一步,使用free命令查看内存,这其实没有什么实际作用,就是做个前后对比;第二步,执行sync命令,是为了确保文件系统的完整性(sync命令将所有未写的系统缓存写到磁盘中);第三步,执行echo3>/proc/sys/vm/drop_caches就开始释放内存了。
这里说明一下/proc/sys/vm/drop_caches的作用:当写入1时,释放页面缓存;#无任何危害写入2时,释放目录文件和inodes;写入3时,释放页面缓存、目录文件和inodes。#缓存目录文件和inodes的目的跟B树缓存根节点和中间节点的原理一样,快速查找叶子节点,快速根据内存中的inode找到datablock
可见,整个操作过程就是释放磁盘缓存。
可以cat一下/proc/sys/vm/drop_caches,看一下之前是否有人改过/proc/sys/vm/drop_caches,在/etc/sysctl.conf或者手动echo3>/proc/sys/vm/drop_caches
cat/proc/sys/vm/drop_caches0
#free-mtotalusedfreesharedbufferscachedMem:996925719187252-/+buffers/cache:484511Swap:20474001647
Linux系统与Windows在对待内存的问题上是持不同意见的。Linux会尽量使用内存来提高效率,free查看剩余内存小并不是说内存不够用,还应该看swap是否被大量使用了。实际项目的经验告诉我们,如果是因为应用程序有内存泄漏、溢出的问题,从swap的使用情况是可以比较快速判断的,查看剩余内存是没有意义的或十分困难的。/proc/sys/vm/drop_caches是直到2.6.16以后的内核版本才开始提供的,我个人认为是内核开发团队对很多用户对Linux内存管理方面的疑问的一个妥协,对于是否需要使用这个接口,或向用户提供这个接口,我是持保留意见的。因为当你告诉一个用户,修改一个系统参数可以“释放内存”,剩余内存就多了,用户会怎么想?难道不会觉得这个操作系统“有问题”吗?这个实战的目的就是想让大家了解,这个接口虽然有提供,但是不要用,因为真的没用。
9.3tmpfs——满足你对“时空”的双重渴望(
tmpfs是一个基于内存的文件系统,不需要格式化,不需要文件系统驱动tmpfs跟普通的用户进程差不多,使用的只是某种形式的虚拟内存。
)前几天闲来无事翻微薄,有人写道:“曾经偷情被游街,如今二奶喊干爹;曾经撞人忙救人,如今撞人再杀人;曾经私情偷着干,如今淫乱存U盘;曾经献血为扶伤,如今慈善越重洋;曾经相好牵肚肠,如今小三炫富忙;曾经摩托都挺酷,如今地铁都追尾;曾经县长坐皮卡,如今少年开宝马;曾经精英成右派,如今牛逼全二代。”不禁感慨万千,这世道真是变了。曾经内存比金子都贵,现在已经白菜价了。有时候我们在设计系统时,如果磁盘已经忙不过来了,完全可以让内存帮帮忙。不但不会有什么损失,整体执行效率几乎会有一个数量级的提升。tmpfs就是让你这么干的一个好帮手。
9.3.2tmpfs文件系统tmpfs类似于RamDisk,它既可以使用内存,也可以使用交换分区(swap分区)。tmpfs文件系统使用虚拟内存(我们后面简称VM)子系统的页面来存储文件,tmpfs自己不需要知道这些页面是在物理内存中还是在交换分区中,一切由VM说了算。所以,tmpfs跟普通的用户进程差不多,使用的只是某种形式的虚拟内存。tmpfs的实现与很多人所理解的完全不同,它跟其他文件系统如:ext3、ext2、ReiserFS等是完全不一致的,它们在Linux中都被称为块设备(即读写大块数据的设备,与之相对应的是字符设备,如键盘、鼠标等)。而tmpfs是直接建立在VM之上的,你用一个简单的mount命令就可以创建tmpfs文件系统了,不需要什么格式化。
事实上就是十分想要格式化你也做不到,因为地球上就不存在类似mkfs.tmpfs这样的命令。
你或许想知道你刚刚挂接地tmpfs文件系统到底有多大。这个问题的答案有点意外:不知道!tmpfs刚被挂接时只有很小的空间,但是随着文件的复制和创建,tmpfs文件系统驱动程序会分配更多的VM,并按照需求动态地增加文件系统的空间。当有文件被删除时,tmpfs文件系统驱动程序会动态地减少文件系统并释放VM资源。循环利用,按需分配。因为毕竟VM比磁盘更贵些,还是慎用为妙。tmpfs可以动态扩缩容
说到速度,虽然它使用的是VM,但是人家也是内存,所以用快如闪电来形容一点都不为过。典型的tmpfs文件系统会完全驻留在物理内存中,读写几乎可以说是不用眨眼睛的。即使用了交换分区,性能仍然是卓越的,只要VM比较空闲了,一部分tmpfs的文件就会被移动到物理内存中,而且不常用的文件,也会被自动交换出去,腾出更多地方给用户进程。显然tmpfs遵循着VM子系统的整体调度策略,相对于RamDisk拥有更好的整体协调性和灵活性。不过说到底,tmpfs还是一个基于内存的文件系统,不要指望这种文件系统会提供什么持久性支持,想想都是错误。因为在这个领域看来,那是没有任何意义的功能。而且人家名字也起的好——tmpfs——就是告诉你,别把这儿当安家立业的世外桃源,这里只是一个驿站,风景虽然恬意,但是想留宿,门都没有。
9.3.3tmpfs实战我一直有一个习惯,就是总不甘于就事论事,一定要把大家往“坑”里带,所以接下来的内容大家要注意,“坑”已挖好,就等你来了。1.使用tmpfs即便tmpfs使用起来可以用轻松加愉快来形容,不过我总是要唐僧几句,讲讲如何使用tmpfs的,乃至在实际中要遇到的问题。要使用tmpfs最基本的就是要把它挂接到文件系统的某一个节点。只需要使用下面这个简单的命令:
#mount–ttmpfstmpfs/tmp这个时候/tmp目录就开始使用tmpfs文件系统了。所有使用/tmp目录作为临时目录的程序都会得到很好的速度提升。简单吧?不过注意,问题很快就会出现。最典型的问题就是用光了VM,虽然不能直接扔给大家一句:“后果自负”。但是你还真得处理好这个后果。首先,tmpfs是根据需要动态增大或减少内存的事实就让人有一个疑惑:如果tmpfs文件系统增大到耗尽了所有VM,结果会是怎样?问题到了这个地步,真的很麻烦。早期内核,比如2.4.4以前的内核,直接宕机,只能重启了事。
#mount-ttmpfs–osize=64mnr_inodes=10gtmpfs/tmp这个命令告诉内核,/tmp所挂接的tmpfs最多只能使用64MB的内存。在实际使用中,这个上限未必够用,或者仍然会导致VM被用光。比较好的方法是利用top工具,来监控一下你的系统在高峰期的内存用量。注意,交换分区要一同算在内。那么高峰期的余量就可以考虑成为tmpfs的上限值。不过最好这个上限值再稍微小那么一点,这样可以给你的系统留出一些余量,来应对一下突发事件。除了容量限制,还可以通过使用nr_inodes=x参数限制一下索引节点数量,可以理解为限制了最大的inode文件数量(限制inode)。这个x可以是一个简单的整数,后面还可以跟一个k、m或g来制定千、百万或十亿个索引节点inode。
#mkdir/dev/shm/tmp#chmod1777/dev/shm/tmp#mount--bind/dev/shm/tmp/tmp这里解释一下
/dev/shm
/dev/shm目录就是大多数发行版提供的一个默认的tmpfs文件系统,这是POSIX标准所规定,因为POSIX标准的共享内存就是利用tmpfs所实现的。不过目前大家常用的还是SystemV的共享内存,POSIX的共享内存不是很流行。这只是当前的情况,将来会怎么样,我是说不清楚。既然/dev/shm就是现成的tmpfs
df-THFilesystemTypeSizeUsedAvailUse%Mountedon/dev/mapper/VolGroup-lv_rootext419G9.0G8.7G51%/tmpfstmpfs521M0521M0%/dev/shm/dev/sdc1ext4500M53M421M12%/boot
那么就在它下面创建一个新的tmp目录。注意要修改权限使得所有用户都能访问(chmod1777),因为这是业界针对/tmp目录的强制规范。最后使用绑定挂接,将/dev/shm/tmp这个tmpfs绑定挂接到/tmp上,这样所有使用/tmp目录作为临时目录的程序都会受益于tmpfs所提供的超高性能。另外,这样操作有一个好处就是,/dev/shm是由发行版本厂商所提供的标准tmpfs,它的最大容量限制一般可以被认为是最为优秀的,直接拿来用总比自己动手分析要容易得多。再针对绑定挂接多说几句。绑定挂接对于程序员来说,是非常实用的一个小帮手。我们假设这样一个场景。在一些特定开发场景,为了测试一些新功能,必须修改某个系统文件。但是这个系统文件又是放在只读文件系统上(只读只是相对的,只是修改这个文件非常麻烦罢了),或者这个文件虽然可写,但是对自己没什么把握,不敢直接修改。那么就可以利用mount--bind绑定挂接一个新的文件系统,你所有的修改都只是操作这个新的文件系统,
老的是不会被改动的。当操作完毕,umount一下,就完全恢复了。即便弄出问题,重新启动一下,就没有任何问题了。
注意:绑定挂接和软链接的区别软链接的目标不能是已存在的#mkdir/dev/shm/tmp#chmod1777/dev/shm/tmp#ln-s/tmp/dev/shm/tmp这时候会报错,因为已经存在/dev/shm/tmp目录
在2G的机器上,将最大容量调到1.5G,并且inode数量调到1000000,这意味着大致可存入最多一百万个小文件。
为当/dev/shm空间不够时可以占用swap的空间,所以不用担心存储空间不够用。想想看,从磁盘IO操作到内存操作,php读写SESSION的速度会快多少?只是需要注意,存储在/dev/shm的数据,在服务器重启后会全部丢失。
二、与swap的区别:/dev/shm首先可以看出来/dev/shm是一个设备文件,可以把/dev/shm看作是系统内存的入口,可以把它看做是一块物理存储设备,一个tmpfilesystem,你可以通过这个设备向内存中读写文件,以加快某些I/O高的操作,比如对一个大型文件频繁的open,write,read,你可以直接对/dev/shm进行读写操作,例如:#touch/dev/shm/file1既然是基于内存的文件系统,系统重启后/dev/shm下的文件就不存在了
Linux默认(CentOS)/dev/shm分区的大小是系统物理内存的50%,虽说使用/dev/shm对文件操作的效率会高很多,但是目前各发行软件中却很少有使用它的(除了前面提到的Oracle),可以通过ls/dev/shm查看下面是否有文件,如果没有就说明当前系统并没有使用该设备.
swap而swap是Linux的虚拟内存,即在硬盘上开辟空间当内存不够时充当内存使用,因此可以理解为当/dev/shm空间不够时可以占用swap的空间。
3.应用加速淘宝,作为一个业内最著名的互联网公司,Web页面是我们对外提供服务的标准接口之一。我想在坐的任何一个人,无不关心Web页面的显示速度。那么就叨唠几句用tmpfs来加速Web页面吧。说到Web,Apache略显老态龙钟,这个时代已经是nginx大行其道的时代,那就看看如何加速nginx吧。还记得前面说过的,使得/tmp目录成为tmpfs的方法吧。不过在实际使用中,我们可能不太想改变/tmp的性质,毕竟还有很多其他程序也要用。
那么我们就单独创建一个/nginx_tmp目录好了。至于是不是这样,你自己决定就行,然后在它上面挂接tmpfs。可以利用/dev/shm,也可以自己设定大小,随你。然后再修改nginx.conf文件,添加如下内容:
#修改nginx的temp目录client_body_temp_path/usr/local/nginx/client_body_temp;proxy_temp_path/usr/local/nginx/proxy_temp;fastcgi_temp_path/usr/local/nginx/fastcgi_temp;ln-s/usr/local/nginx/client_body_temp/dev/shm/client_body_templn-s/usr/local/nginx/fastcgi_temp/dev/shm/fastcgi_templn-s/usr/local/nginx/proxy_temp/dev/shm/proxy_temp
9.4devfs和sysfsdevfs和sysfs它们来了,真的来了,一前一后来的,来得是那么突然,来得是那么悄无声息。一个脸色苍白,苍白得让人不寒而栗;一个目光深邃,深邃得让人顿觉谦卑。人们一直在谈论着它们,据说先来的已经死了,死得很透彻,是被它的门人杀死的,而且居然是后来者收买了它的门人,后来的现在还在收买其他门派的门人,正在觊觎“武林盟主”的地位。所有的事情就这么潜移默化地变化着,轮替着。一切看似那么平静,平静得已经让很多人开始摩拳擦掌。在这平静之中不知何时又要到来一场可怕的血雨腥风。故事是这样开始的……
现在要说的是,它解决了一个更要命的问题。什么问题呢?设备号的问题。传统的Linux设备驱动程序,要向系统提供一个文件映射,需要提供一个主设备号,而且这个主设备号必须保证唯一。
由于历史原因,早些年内存比黄金还贵,这个主设备号被设计的只有8位,显然这是稀缺资源啊,在它面前,黄金都只能汗颜了。既然这样,开发人员自然不能凭空臆造一个主设备号了,只能联系Linux内核的开发人员来申请,如果人家正忙着呢,那您就只能等,还不能歇,一歇就麻烦了,因为等待申请的人多了去了。所以,您就甘心地在那儿耗着吧。直到人家看你是个虔诚的主儿,偶发恻隐之心,给您分配了一个“正式”的主设备号,您才算万事大吉收工交差。其实后面的事情远没有这么简单,只是那已经是历史,我就不多叨唠了。至于这种策略的后果是什么,我不说,谁都知道。反正很难想象,早年的Linux用户真是有够虔诚,要不然现在还有谁会知道有Linux这个玩意儿呢?不管devfs的命运如何,但就仅仅是把这个滥问题给解决了,就可以称之为伟大,何况这只是其中的一个部分呢?
sysfs如今大红大紫,procfs的命运如何,还需要你我共同的期待。
9.5其他特种文件系统都说知足者常乐,但是往往就有那么一些人,以发现不足为己任,以满足不足为乐趣。于是就有了四大发明、有了飞机大炮、有了UNIX、有了Linux、有了你我今天所面对的世界。
9.5.2debugfs顾名思义,这就是用于调试用的。不过这个只是用于调试内核用的。应用程序员就不要打它的主意了。debugfs是基于relay技术实现的。因为relay可已极快地将大量的内核空间数据反馈给用户空间,效率是远高于传统的printk的。所以使用debugfs可以获取更多的调试信息,且占用CPU资源更少。由于是基于文件系统的,使用起来会更加方便。毕竟它不会让你的屏幕乱糟糟。最后说一句就是,想学习内核开发的,就开始使用debugfs吧,绝对是你的好帮手。
9.6结束语
有关Linux特种文件系统的一些故事到此就算讲完了。类似devfs和sysfs这样的惊心动魄的江湖地位争夺战,在Linux世界无时无刻不在上演着。其实我不单单是希望大家通过对特种文件的了解而更明细地认识Linux,更希望的是通过这一个个案例,来展现Linux能够玉树常青的不二法则——新的系统并不是只为了做同样的事情比老的系统快一点,还应该允许我们用以前完全不可能的方法来处理事情,去感受Linux世界文化的深邃与博大。就像sysfs最终干掉了devfs。在Linux界是允许造反的,只要你能,我们就说:造反无罪,造反有理。