操作系统和Web服务器那点事儿

又一个进程启动了,操作系统老大叹了一口气,毕竟自己的肩头又多了一份责任。

让人烦恼的是,新来的家伙们很无知,几乎就是一张白纸。有些老实本分的会按照自己的规矩来做事,有些刺头儿喜欢问这问那,时不时还想搞点非法的访问,想访问别的进程的地址空间,甚至想访问内核的代码和数据! 这时候,我只有把他kill掉祭天,留下一个core dump的尸体让码农们去分析。

规矩很重要!

想到此处,老大又看了一眼自己的内核空间,这个机器只有可怜巴巴的4G内存,0-3G给各个进程共享使用,自己独占了从3G-4G的内存空间。

新启动的进程是一个Web服务器,自称小W,这是个喜欢问问题的家伙,他第一个问题就是: ”老大,你为啥不和群众打成一片,反而自己要独占空间呢?“

“这是为你们好?”

“为我们好? ”

“计算机的硬件资源是有限的,硬盘、内存、网卡,键盘,鼠标,时钟...... 如果任由你们这些进程随意访问,大家你争我抢,岂不乱套?”

“再说了,那些底层的硬件、驱动操作是极其麻烦的,让你们每个进程都去写那些‘恶心’的代码,你们受得了吗? “

”还有,如果某个恶意的家伙故意捣乱,那还了得?”

老大的三连问简直是振聋发聩, 小W立刻觉得气短了三分。

“所以你就不让我们直接访问了?”

“对啊,我就做了一个抽象层,你们必须通过这个抽象层来访问硬件资源。这个抽象层之下就是我的内核,是我的代码和数据,所以我必须得单独居住,不能和你们混在一起。”

系统调用

“那我想访问一个硬盘上的文件,到底该怎么办?” 小W问道。

“非常简单,我的抽象层中有对外提供的接口,叫做系统调用,例如read、open、close等。 你可以open 一个文件,read它的内容,读完了close。”

“听起来好像是函数调用啊!”

“对,就是函数调用,但是和你内部的函数调用有本质的不同,这种系统调用会让你从用户态切换到内核态, 也就是到我的内核代码中来执行!”

小W懵懂地点点头,似乎明白了。

他应该没有明白,他也明白不了, 操作系统老大心里想,系统调用之复杂远远超过他的想象。

首先所有Linux的系统调用的参数都是通过寄存器而不是栈来传递的,按照惯例寄存器EAX保存了系统调用的编号(例如1表示exit这个系统调用,2表示fork,3表示read......),寄存器EBX,ECX,EDX,ESI,EDI可以包含最多6个任意的参数。

比如:write(1,"hello",5);

这就是个系统调用, 就是向stdout(控制台)输出一个字符串,在运行时,必须把寄存器给设置好:

EAX = 4 (4表示系统调用的编号)

EBX = 1 (1 表示stdout)

ECX = 那个字符串的地址

EDX = 字符串的长度

然后调用int 0x80 系统中断,这就进入了内核, 我会取出EAX, 从一个内核的表格中查到第4号对应的系统调用处理程序来执行。

对了,我还需要把CPU的特权等级从3置为0,表示内核态。

看看,我容易吗我! 操作系统心里略微有点伤感。

read 和 write

这时候小W探出头来,兴奋地说:“hi ,老大,有客户要访问咱们硬盘的文件,我得读取一下,然后通过socket发出去。是不是需要系统调用了?”

“那是肯定的,访问文件系统必须得通过我,访问socket也得通过我,不用系统调用怎么可能? 除去open ,close, 你需要两个关键的系统调用:”

// 从文件(用fd表示)中读取len长度的内容,放到buffer中

read(fd, buffer, len);

// 把buffer中长度为len 的内容写入到socket中(用sockfd表示)

write(sockfd, buffer, len);

(注: read和write 应该是sys_read和sys_write的“包裹”函数,我们这里简化,认为就是直接的函数调用。)

“好滴!” 小W做了一些准备工作,然后便开始read, 然后满心欢喜地等待数据的到来。

操作系统收到read调用,陷入内核,正式进入了内核态,然后毫不客气地暂停了小W的执行,让他进入了阻塞队列(假设小W只有一个线程)。

小W表示不满:“怎么不让我运行了?”

“读取文件太慢,你先歇会儿,数据来了会通知你的。”

老大使用DMA(Direct Memory Access)的方式把文件的数据从硬盘复制到了内核的缓冲区, 然后又复制到了用户的缓冲区,read调用完成,返回用户态 ,小W可以继续执行了。

小W要通过socket发送数据,于是又发出了write调用,再次陷入内核,进入内核态。

老大把数据又从用户缓冲区复制到socket缓冲区, write调用返回,返回用户态。

小W问道:“这次这么快就返回了?数据发出去没有啊?”

老大说:“这就不用你操心了,网卡驱动会在合适的时候发送的,这是个异步的操作。”

小W画了一张图,试图理解整个过程,等他把图画完,不由得咂舌:“啧啧,这么两个简单的系统调用,代价竟然如此之高啊。”

(1) 需要进入内核态两次,返回两次。

(2) 数据居然发生了三次复制,硬盘-->内核缓冲区-->用户缓冲区-->socket缓冲区

如果说第一次从硬盘到内核缓冲区必不可少,后面的两次就太浪费了。

老大说:“你看到了吧,系统调用的开销很大啊,以后要少点调用啊。”

小W说:“我觉得你这个内核虽然保护了硬件,但是导致效率很低啊,能不能优化一下,省去用户态<-->核心态之间的数据复制? 这太浪费了!”

sendfile

老大哈哈一笑, 说道: “我早就料到了这一层,我这里还有个系统调用,叫做sendfile,你可以试试啊,通过这个系统调用,可以直接把文件内容发给socket。 ”

sendfile(socket, file, len);

小W一看,不错啊,自己只需要调用sendfile,进入内核态一次就可以了,老大可以把数据从硬盘复制到内核缓冲区,然后直接复制到socket缓冲区, 完全不用自己介入,就用它了!

可是转念一想,这从内核缓冲区到socket缓冲区的复制有必要吗? 那个网卡驱动不能直接从内核缓冲区读数据吗?

老大似乎看穿了小W的心思,说道:“我知道你在想啥,放心吧, 我早就做了优化了,不会把数据从内核缓冲区复制到socket缓冲区,相反,我只会把一些位置和数据长度等信息复制过去,很省事的。网卡驱动可以直接从内核缓冲区读去数据。”

小W放心了,开始使用这种sendfile的方式,果然,性能大为提升!

简约山峰分割线

这其实就是所谓的zero copy技术, 从内核角度看,除了把文件从硬盘读出来之外,没有任何的额外copy。

zero copy技术减少了上下文的切换,避免了数据不断地在用户态和核心态搬运,不需要CPU参与数据的复制,提高了系统性能,在ngnix, apache等web 服务器中都引入了zero copy技术。

原文地址:http://blog.51cto.com/13961945/2285349

时间: 2024-08-24 02:04:29

操作系统和Web服务器那点事儿的相关文章

看看大网站都用什么操作系统和Web服务器

以下内容为网络上转载总结,不是很准确 Google 用哪些软件做 Web Server? 除了有两个节点操作系统看出来是 Linux 外,其他的都是未知的. Web 服务器用的都是 GWS ? 我估计是 Google Web Server 的缩写. Yahoo! 操作系统都是 FreeBSD. 其他的都不可知.Yahoo! 的网络安全据说是一级棒! 微软 操作系统全是 Windows 2003(如果使用 Linux 会被笑死) , 看来 Windows 2000 已经退出微软自己的舞台.Web

初识操作系统和linux

初识操作系统和linux 1.计算机系统由硬件系统和软件系统两大部分组成:是一种能接收和存储信息,并按照存储在其内部的程序对海量数据进行自动.高速地处理,然后把处理结果输出的现代化智能电子设备. 2.世界上第一台计算机是1946年诞生在美国宾州大学. 3.冯·诺依曼体系结构:1946年数学家冯·诺依曼于提出计算机硬件系统由运算器.控制器.存储器.输入设备.输出设备.摩根定律:当价格不变时,集成电路上可容纳的元器件的数目,约每隔18-24个月便会增加一倍,性能也将提升一倍.现在计算机技术进本很难遵

一种基于uCos-II操作系统和lwIP协议栈的IEEE-1588主站以及基于该主站的报文处理方法

本发明公开了一种基于uCos‐II操作系统和lwIP协议栈的IEEE‐1588主站以及应用于电力系统的支持IEEE‐1588协议的主时钟(IEEE‐1588主站)的实现方法.该方法是在一个低成本的硬件平台上,借助uCos‐II操作系统和TCP/IP的协议栈,对以太网数据进行了分类处理,实现了在同一个以太网端口提供基于二层和三层报文交换的IEEE‐1588的主站功能.另外,通过使用不同的操作系统进程来处理E2E和P2P对时,实现了两种对时模式在同一端口上的共存. 技术领域 [0001] 本发明属于

操作系统和Python的发展历程

操作系统的发展历史: 操作系统:什么是操作系统?我们首先想到的是电脑,,也就是所谓的Windows8,Windows7,或者XP系统和Windows10,当然也包括我们手机的安卓系统或者IPhone的IOS系统,但是有没有一个具体的定义呢?操作系统(英语:Operating System,简称OS)是管理和控制计算机硬件与软件资源的计算机程序,是直接运行在“裸机”上的最基本的系统软件,任何其他软件都必须在操作系统的支持下才能运行.我们的手机在不断的升级,那么系统肯定也是,所以就让我们来简单的回顾

windows操作系统和java常识

一.java5和java8版本更新很大,现在都是java8; 二.数据存储最小单位Byte字节八个比特位: 三.没有图形操作界面的windows系统: 四.java语言跨平台性:JVM充当不同操作系统的翻译功能: 五,oracle官网下载jdk安装,安装路径不要有中文不要有空格,防止乱码和转义的问题: windows系统文件路径部分大小写: 六.配置java环境变量,让windows操作系统认识它: 认识之后,cmd重新打开,再输入”java“,就可以不写全路径也能搜索到: 原文地址:https

【嵌入式开发】裸机引导操作系统和ARM 内存操作 ( DRAM SRAM 类型 简介 | Logical Bank | 内存地址空间介绍 | 内存芯片连接方式 | 内存初始化 | 汇编代码示例 )

[嵌入式开发]ARM 内存操作 ( DRAM SRAM 类型 简介 | Logical Bank | 内存地址空间介绍 | 内存芯片连接方式 | 内存初始化 | 汇编代码示例 ) 一. 内存 简介 1. 两大内存分类 ( 1 ) DRAM 简介 ( 定期刷新 | 速度慢 | 成本低 ) DRAM 简介 : 1.硬件描述 : DRAM 基本由一个个小电容基本原件组成, 电容的两端保留电荷; 2.优缺点描述 : ① 优点 : 成本很低, 很便宜; ② 缺点 : 需要 定期刷新数据, 速度较慢; a.

谈谈三大现代操作系统和MAC开发的经典书籍

闻道有先后,术业有专攻,这句话放到计算机科学领域的理解可能每个人都会不同. 有些人选择一个操作系统,一个体系的编程语言,作一个领域的开发. 有些人选择多个操作系统,多个体系的编程语言,作多个领域的开发. 其实这都没有错,笔者倾向于后者,因为笔者始终认为,只要不跑出计算机科学的领域,就算术业有专攻了:) 当前的世界排名前三的操作系统分别是Windows NT体系, MAC OSX体系,Linux/Unix体系, iOS和 Android分别属于MAC OSX体系和Linux/Unix体系,那么为什

实现windows操作系统和VB下Linux虚拟操作系统相互传取文件方式总结

在windows上执行虚拟机跑的是Linux的操作系统,怎样才干在不同的操作系统之间传递文件呢? 这是本人切身体会到的,假设你没有好的方法的话.确实非常痛苦.下面是我个人的方法总结: 方法一.很好用的:***** 使用一个winscp的软件,它是windows环境下使用ssh的开源图形化SFTPclient,同一时候支持SCP协议.它的主要功能就是在本地与远程计算机间安全地拷贝文件. 强力推荐,是一个exe文件.双击就能够实现. 假设想要这软件,能够评价说下. 推荐一下载网址:http://ww

Ubuntu下部署Apache Web服务器操作手册

Ubuntu下部署Apache Web服务器操作手册 安装 sudo apt install apache2 –y 修改配置 所有配置文件默认为只读,修改时需要修改操作权限: sudo chmod 777 [文件名] 修改/etc/apache2/sites-available路径下的000-default.conf文件中的DocumentRoot /var/www/ 为想要的目录: 修改/etc/apache2路径下的ports.conf文件中的Listen 80 为想要的端口,如8888: