为已编译的apache2添加mod_proxy模块 和应用
http://help.lampok.net/log/?p=1525
这篇文章试过可以,在apache2.2.23版本的时候。
blog.51yip.com/apachenginx/873.html
http://shiningray.cn/proxypass-directive-in-apache.html
查看apache支持的模块:
httpd -l
查看apache载入的模块:
httpd -t -D DUMP_MODULES
使用apache扩展工具apxs可以为apache编译和安装扩展模块。新安装的模块将作为动态共享对象提供给apache,因此,apache运行的平台必须支持DSO特性,并且httpd必须内建mod_so模块。这样才能使用mod_so提供的LoadModule指令在运行时将模块加载到apache服务器中。
要为已运行的apache添加mod_proxy模块,先定位到apache源码中modules/proxy目录。然后使用apxs进行编译安装:
/usr/local/apache2/bin/apxs -i -c -a mod_proxy.c proxy_util.c
-c表示进行编译,-i表示将生成的模块安装到apache的modules目录下,-a选项在httpd.conf中增加一条LoadModule指令以载入刚安装的模块,或者如果此指令已存在,则启用之。
apxs会根据源码判断模块的名称,或者(在失败的情况下)根据文件名推测模块名称,可以用-n选项显式地指定模块名称。
安装成功以后将在apache的modules目录下生成mod_proxy.so文件,并且在httpd.conf中加入了一行
LoadModule proxy_module modules/mod_proxy.so
proxy只是核心模块,具体使用时还需要其它模块的支持,安装方法类似。
/usr/local/apache2/bin/apxs -i -c -a mod_proxy_http.c
/usr/local/apache2/bin/apxs -i -c -a mod_proxy_ftp.c
/usr/local/apache2/bin/apxs -i -c -a mod_proxy_connect.c
同样,安装后在apache的modules目录中生成了mod_proxy_http.so, mod_proxy_ftp.so, mod_proxy_connect.so文件。并且在httpd.conf中添加了如下行:
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so
这样,mod_proxy模块就安装好了,进行具体的应用配置,重启apache就可以了。
要求:
运行多个tomcat,通过apache侦听的端口进行区分。
对于每个tomcat,配置各自需要服务的虚拟主机
使用Apache的Proxy进行代理转发,转到对应的tomcat上面,重点在端口不同
取消jk连接,减少复杂度。虽然损失了一些Apache对静态文本的性能,但整体看还是值得的
结果:
tomcat的server.xml里面配置了各自的虚拟主机,比如 www.lampok.net 和 oa.lampok.net。第一个是主域名,第二个是二级域名。tomcat端口为8080。第二个tomcat配置了一个 sales.lampok.net 用来支持销售,端口为8081。详细的配置文件请参考tomcat的虚拟主机配置,这里就不写了。
测试各个虚拟主机的运行是否正常,使用 http:// oa.lampok.net:8080/ 这样的方式进行测试。
apache的 httpd.conf配置
打开代理所需要的.so支持模块,在httpd.conf里面,取消下面四行的注释:
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
制作各自的虚拟主机
NameVirtualHost *:80
<VirtualHost *:80>
ServerName www.lampok.net
ProxyPass / http://www.lampok.net:8080/
ProxyPassReverse / http://www.lampok.net:8080/
</VirtualHost>
<VirtualHost *:80>
ServerName oa.lampok.net
ProxyPass / http://oa.lampok.net:8080/
ProxyPassReverse / http://oa.lampok.net:8080/
</VirtualHost>
<VirtualHost *:80>
ServerName sales.lampok.net
ProxyPass / http://sales.lampok.net:8081/
ProxyPassReverse / http://sales.lampok.net:8081/
</VirtualHost>
若需要内部端口整合
ProxyPass / ajp://localhost:8009/
ProxyPassReverse / ajp://localhost:8009/
现在我们编辑第一个tomcat配置文件,端口为默认的8080
<Engine name=”Catalina” defaultHost=www.lampok.net>
<Host name=www.lampok.net appBase==”/www/lampok.net/htdocs” unpackWARs=”true” autoDeploy=”true” xmlValidation=”false” xmlNamespaceAware=”false”
<Host name=www.cba.com appBase==”/www/cba.com/htdocs” unpackWARs=”true” autoDeploy=”true” xmlValidation=”false” xmlNamespaceAware=”false” />
源码编译安装proxy-ajp模式的
# tar xvjf httpd-2.2.0.tar.bz2
# cd httpd-2.2.0
安装apr
# cd srclib/apr
# ./configure –prefix=/server/soft/apr
# make
# make install
安装apr-util
# cd ../apr-util/
# ./configure –prefix=/server/soft/apr-util \
–with-apr=/server/soft/apr
# make
# make install
# cd ../../
安装apache
# ./configure –prefix=/server/soft/apache \
–enable-so \
–enable-rewrite=share \
–enable-proxy=share \
–enable-proxy-ajp=share \
–enable-dav=share \
–with-apr=/server/soft/apr \
–with-apr-util=/server/soft/apr-util/
# make
# make install
</Engine>
注意:网站文件请分别放在/www/*/htdocs/ROOT目录
Host name=”localhost” appBase=”webapps” unpackWARs=”true” autoDeploy=”true” xmlValidation=”false” xmlNamespaceAware=”false” />
</Engine>
编辑第二个tomcat配置文件,端口修改为8081
<Engine name=”Catalina” defaultHost=localhost>
<
注意:网站文件放在tomcat安装文件目录的默认ROOT目录
localhost这里可以不用修改,因为只有一个网站,我们就可以不用域名代替
附出错分析:
如果编译安装没有编辑代理模块的解决办法
方法如下:
编译的时候要打开WITH_PROXY_MODULES选项,但我又不想重新安装apache,所以使用以下步骤达到此目的。
1、重新编译带有proxy模块的apache,但不安装。
进入源代码目录
#cd /usr/loacl/src/httpd2.2.9
#make WITH_PROXY_MODULES=yes
2. 分别编译生成代理模块
cd modules/proxy
/usr/local/apache/bin/apxs -c -i -a mod_proxy.so proxy_util.c
/usr/local/apache/bin/apxs -c -i -a mod_proxy_ajp.so mod_proxy_ajp.c
/usr/local/apache/bin/apxs -c -i -a mod_proxy_connect.so mod_proxy_connect.c
/usr/local/apache/bin/apxs -c -i -a mod_proxy_http.so mod_proxy_http.c
/usr/local/apache/bin/apxs -c -i -a mod_proxy_ftp.so mod_proxy_ftp.c
这样就编译进了apache配置文件
编译过程中或者会出错,因为权限原因,需要给755权限
chmod 755 /usr/local/apache/modules/*.so
查看httpd.conf文件显示已经添加了代理模块
以下是httpd.conf的部分显示
# Example:
# LoadModule foo_module modules/mod_foo.so
LoadModule php5_module modules/libphp5.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
#
已经添加进了apache,现在需要重新启动apache,就可以正常配置代理方式了
#配置(prefix是安装路径,enable-mods-shared=all表示编译配置所有so文件)
./configure –prefix=/usr/local/apache –enable-mods-shared=all
php编译案例:
./configure –prefix=/usr/local/php5 –with-apxs2=/usr/local/apache2/bin/apxs –with-config-file-path=/usr/local/php5 –disable-debug –enable-ftp –enable-inline-optimization –enable-magic-quotes –enable-mbstring –enable-safe-mode –enable-wddx=shared –with-gd –with-gettext –with-regex=system –with-zlib –with-mcrypt –enable-sockets
单独编译apache可以进行这样的操作
[root@localhost apache]#./configure –prefix=/usr/local/apache –enable-so –enable-mods-shared=”proxy proxy_http proxy_ftp proxy_connect headers”
编译
[root@localhost apache]# make
检查编译后的是否有编译出so文件
[root@localhost apache]# cd /usr/local/apache/modules
[root@localhost modules]#]# ls
httpd.exp mod_proxy_ajp.so mod_proxy_connect.so mod_proxy_http.so
mod_headers.so mod_proxy_balancer.so mod_proxy_ftp.so mod_proxy.so
如果存在以上文件则说明编译成功
安装
[root@localhost apache]# make install
启动APACHE
[root@localhost apache]# /usr/local/apache/bin/httpd -k start
测试如果输出IT works那么就ok了
附:
tomcat 404页面设置方法在web.xml里面加入
<error-page>
<error-code>404</error-code>
<location>/404.jsp</location>
</error-page>
添加404.jsp页面文件,重新启动tomcat可生效
别忘记 proxy_util.c 然后,我加载它 # /usr/local/apache/bin/apxs -c -i -a proxy_util.c 加载的时候出现报错: /usr/local/apache/build/libtool –silent –mode=compile gcc -prefer-pic -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -D_LARGEFILE64_SOURCE -g -O2 -pthread -I/usr/local/apache/include -I/usr/local/apache/include -I/usr/local/apache/include -c -o proxy_util.lo proxy_util.c && touch proxy_util.slo /usr/local/apache/build/libtool –silent –mode=link gcc -o proxy_util.la -rpath /usr/local/apache/modules -module -avoid-version proxy_util.lo apxs:Error: Sorry, cannot determine bootstrap symbol name. apxs:Error: Please specify one with option `-n’. |
APACHE中增加模块遇到的问题
用apxs 安装apache mod_proxy时候出现undefined symbol: ap_proxy_lb_workers错误的解决方法
在用apxs安装apache mod_proxy时候出现undefined symbol: ap_proxy_lb_workers的错误,原先用的是:
apxs -i -a -c mod_proxy.c
错误信息:
httpd: Syntax error on line 19 of /opt/lamp/apache2/conf/httpd.conf: Cannot load /opt/lamp/apache2/modules/mod_proxy.so into server: /opt/lamp/apache2/modules/mod_proxy.so: undefined symbol: ap_proxy_lb_workers
原来需要加上proxy_util.c一起编译:
apxs -i -a -c mod_proxy.c proxy_util.c 问题解决。因为proxy_util.c是基础模块,所以必须先安装。下面也是安装方法。 先安装基础模块:
# /usr/local/apache2/bin/apxs -c -i mod_proxy.c proxy_util.c
# /usr/local/apache2/bin/apxs -i -a -n proxy mod_proxy.la
再安装mod_proxy_http模块
# /usr/local/apache2/bin/apxs -c mod_proxy_http.c
# /usr/local/apache2/bin/apxs -i -a -n proxy_http mod_proxy_http.la
再去看httpd.conf时,已添加如下内容:
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
重新启动没有任何报错信息,证明mod_proxy_http模块加载成功。 注:我在安装proxy_http.c的时候,用的是 /usr/local/apache2/bin/apxs -i -a -n http mod_proxy_http.la这样的一个命令,所以在配置文件中 LoadModule http_module modules/mod_proxy_http.so 为这样一条语句, 重启的提示为 [root@localh proxy]# /usr/local/apache2/bin/apachectl configtest
httpd: Syntax error on line 55 of /usr/local/apache2/conf/httpd.conf: Can't locate API module structure `http_module' in file /usr/local/apache2/modules/mod_proxy_http.so: /usr/local/apache2/modules/mod_proxy_http.so: undefined symbol: http_module
至于我为什么要/usr/local/apache2/bin/apxs -i -a -n http 这样写, 而不/usr/local/apache2/bin/apxs -i -a -n proxy_http mod_proxy_http.la 这样写(注意我说的是标红的地方) 是因为我受到前面在加模块时看到的文章也出现过这样的提示,是因为我的不符合语法。所以才那样些,现在看来http的必须需要安装proxy_http 这样些至于原因等我找到答案后在做解释。(我怀疑因为proxy_http 是proxy的一个子模块,所以需要这样写的,如果直接的一个模块就不需要—了) |
(二)编辑增加cache模块遇到的问题。下面是我引用的http://qbaok.blog.163.com/blog/static/10129265200981642957718/这里面的文章,再这里感谢作者的文章给我的帮助,这也是我在配置时遇到的问题,我也就直接都拿过来了,希望作者不要介意。
配apache mod_cache 后 httpd -k start
apache出现以下信息:
Cannot load /usr/local/apache/modules/mod_cache.so into server: /usr/local/apache/modules/mod_cache.so: undefined symbol: cache_generate_key_default
正规解决方案:
modules/cache下面有很多的.c文件,大致用途如:
mod_cache.c 编译得到mod_cache.so 主要用来控制整个apache的cache功能。
mod_file_cache.c,mod_mem_cache.c,mod_disk_cache.c这个三个文件编译后得到各自的cache支持模块。
mod_cache.c还需要其他的程序来进行工作,包括cache_*.c这些文件。因此apxs动态加载一个模块的时候,需要把这些文件和mod_cache.c 一起编译:perl /usr/local/apache2/bin/apxs -cia mod_cache.c cache_util.c cache_cache.c cache_storage.c cache_pqueue.c cache_hash.c
上述是我遇到问题,照着上面作者的做法做后问题解决。
在这里我要对我上面的文章中标金黄的部分做一下解释。
在我仔细看了配置文件,详细的做了对比,
LoadModule logio_module modules/mod_logio.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule cache_module modules/mod_cache.so
LoadModule mem_cache_module modules/mod_mem_cache.so
LoadModule disk_cache_module modules/mod_disk_cache.so
注意到这些modules/mod_proxy.so、modules/mod_proxy_http.so模块和前面的写法了没,proxy_module、proxy_http_module这些写法都是根据modules/mod_proxy.so、modules/mod_proxy_http.so这来的,如果这是mod_proxy.so,则在前面些proxy_module,如果是mod_proxy_http.so则在前面写proxy_http_module。所以我在写mod_mem_cache.so这个的时候,不用想就写了LoadModule mem_cache_module ,这样在检查配置文件的时候也没有提示错误,直接提示ok。以后写的时候,就可以这样写了,我认为是不会有错误的
Posted by 王 风达
最近有个需求,原本一个动态的站点,有些页面要静态化。但是静态化的文件又不希望和动态程序放在一起。并且URL也不希望发生变化,于是考虑使用Rewrite来实现。下面是一些使用的心得。
1、使用Rewrite规则来实现
Apache 的 Rewrite 是一个非常强大的工具,他的手册提供了丰富的实例可供我们学习,利用下面这个规则,可以将对www.a.com 这个网站的特定请求都定向到 www.b.com 服务器上。
ServerName www.a.com
RewriteEngine On
RewriteRule ^/a/(.*) http://www.b.com [P]
2、使用反向代理
ProxyRequests Off
ProxyPass /a http://house.baidu.com/bj
ProxyPassReverse /a http://house.baidu.com/bj
ProxyPassReverseCookieDomain data.house.sina.com.cn l.house.sina.com.cn
ProxyPassReverseCookiePath / /a/
ProxyErrorOverride On
这两种方法都可以实现用 http://www.a.com/a/abc 的形式来访问实际上是 http://www.b.com/abc 的内容
但是,如果用户输入的URL在 www.b.com 中并不存在,www.b.com 发生转向时,会显示 www.b.com 的url
如果 www.b.com 上全是静态文件,文件无法访问到的时候,会导向404页面,默认导向被代理服务器的404。
但是使用
ProxyErrorOverride On 命令后,可以使用代理服务器的404页面。
访问的目标文件中,对于JS和CSS的链接。如果采用了相对链接,则会默认去 www.a.com 上请求相应的文件。
使用代理模式时,页面中对于Cookie的操作可能会有问题。以l.house.x.com.cn代理到data.house.x.com.cn做了实验,
bj/search/0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-1.html 页面中的浏览历史出现了问题。
该指令允许你将一个远端服务器映射到本地服务器的URL空间中,此时本地服务器并不充当代理角色,而是充当远程服务器的一个镜像。
ProxyPass 支持构建一个连接池来提高服务器的服务性能。配置形式为在 URL 后面追加参数,如下:
ProxyPass /example http://backend.example.com smax=5 max=20 ttl=120 retry=300
其中
smax 表示Apache根据需要创建的连接数量。这些数量会在 ttl 设置到期前被 Apache 关闭。
max 表示 允许与被代理服务器链接的最大数量。默认的链接数量,是当前MPM中配置的最大链接数。在Prefork 模式中,这个数值永远是1.
在 Woker 模式中,连接数量由子线程来控制(ThreadsPerChild)。Apache创建的连接数量不会超过配置的数目。
ttl 表示以秒为单位,超过 smax 允许的非活动链接的存活时间。Apache会关闭超过 ttl 设置的非活动链接。
retry 表示连接池中为每次请求进行重试的最大时间限制,单位为秒。如果与被代理服务器之间的连接出现了问题,Apache在这个时间到期前,不会向客户端返回错误。
可以利用这个时间,对被代理服务器进行维护或重启等操作。
对于被代理服务器返回的重定向信息,可以使用 ProxyPassReverse 对其中的URL进行修改。只有明确指定的应答头会被重写,其它应答头保持不变,并且HTML页面中的URL也不会被修改。如果被代理的内容包含绝对URL引用,那么将会绕过代理。有一个第三方模块可以检查并改写HTML中的URL引用,该模块就是Nick Kew编写的mod_proxy_html。
综合起来,要想实现这个目的,就必须使用 apache 的反向代理模块。
本文转载至鞋
Apache httpd +tomcat ProxyPass应用宕机处理总结
http://crazoy.iteye.com/blog/1671715
系统采用Apache http server+Tomcat部署,最近总是出现登陆不上的问题,开始每天总是偶尔有那么几分钟怎么也登不上去,由于供应商在处理我也没怎么在意。可最近这几天开始经常性出现,没办法,动手解决一下。记录一下经过。
系统部署在统一服务器上,应用部署了三个tomcat server,jvmRoute分别为t1,t2,t3,采用AJP/1.3协议,端口分别配置为9013,9023,9033,tomcat的http端口分别为:8013,8023,8033,maxThreads 设为1000,httpd采用ProxyPass做了负载均衡的映射,数据库为Oracle 12g。
开始用
ps -ef | grep httpd | wc -l
查看了一下httpd的进程数,工作正常时间低于100,问题不大。
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
查看tcp连接统计:
TIME_WAIT 410
FIN_WAIT2 2
ESTABLISHED 1585
看上去好像是连接用光了。
看apache error_log日志:
[Tue Sep 04 18:39:55 2012] [error] (104)Connection reset by peer: ajp_ilink_receive() can't receive header
[Tue Sep 04 18:39:55 2012] [error] ajp_read_header: ajp_ilink_receive failed
[Tue Sep 04 18:39:55 2012] [error] (120006)APR does not understand this error code: proxy: read response failed from (null) ($IP)
看来是proxy得不到响应,于是上度娘,没什么结果。公司的网络google不给力,找半天没结果。
看看天色渐晚,已经19:00多了,心下着急,还想着回家吃饭。
决定跟踪一下端口:
netstat -apn | grep "*:80"
已经下班了,数目为个位数,系统基本没人用。
跟踪9013,9023,9033
netstat -apn | grep 9013
netstat -apn | grep 9023
netstat -apn | grep 9033
竟然都是满的。
而客户端通过apache仍然连不上,但是直接连接tomcat的8013,8023,8033端口是可用的。
至此可以断定是apache连接tomcat出了问题,但什么原因造成的,不知道。为了赶时间,就果断restart了tomcat,世界清净了。
晚上回家google了一下,搜到[2],apache bug 38227, 似乎从httpd2.2.2就已经修复了这个bug。
早上来到公司,检查了一下版本,2.2.22,真够2,问题还在。看了apache日志,重启后,一切都很正常,看连接数,用户也不多,3个jvmRoute只有一个9033端口在被占用。
打开日志开始观察:
apache httpd:
tail -f error_log
apche tomcat:
tail -f localhost.2012-09-05.log
过了一会问题出现了,httpd报错
[Wed Sep 05 09:42:14 2012] [error] ajp_read_header: ajp_ilink_receive failed
[Wed Sep 05 09:42:14 2012] [error] (70007)The timeout specified has expired: proxy: read response failed from 172.16.5.68:18033 (172.16.5.68)
[Wed Sep 05 09:42:28 2012] [error] (70007)The timeout specified has expired: ajp_ilink_receive() can't receive header
追踪到tomcat:
2012-9-5 9:47:06 org.apache.catalina.core.StandardWrapperValve invoke
严重: Servlet.service() for servlet service threw exception
com.mchange.v2.resourcepool.TimeoutException: A client timed out while waiting to acquire a resource from com.mchange.v2.resourcepool.BasicResourcePool@67cec874 -- timeout at awaitAvailable()
at com.mchange.v2.resourcepool.BasicResourcePool.awaitAvailable(BasicResourcePool.java:1317)
at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:557)
at com.mchange.v2.resourcepool.BasicResourcePool.checkoutResource(BasicResourcePool.java:477)
at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:525)
at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.getConnection(AbstractPoolBackedDataSource.java:128)
度娘上搜了一下,找到了[3],心下吸了口凉气。看来是数据库死锁导致了tomcat连接被占,时间长了就没法应对ajp的请求,导致系统当掉。
调了一下数据源的配置,以观后效了。
实在不行准备用终极大招,定时轮流restart tomcat server了。
参考:
[1] http://www.2cto.com/os/201205/130110.html
[2] https://issues.apache.org/bugzilla/show_bug.cgi?id=38227
[3] http://aijuans.iteye.com/blog/1478466
ERROR: date.timezone not set in php.ini. Please contact your hosting company to set the timezone in the server PHP configuration before continuing.
今天安装网站碰到一个问题.说是时区的问题.
网上说改php.ini的date.timezone=PRC
find / -iname php.ini -print
用命名查找出php.ini的位置
用命名查找timezone
grep timezone /usr/local/Zend/etc/php.ini -r
用命名修改,修改之前记得备份cp /home/field/etc/php5/php.ini /home/field/etc/php5/php.ini.back
sed -i "s/;date.timezone=/date.timezone = PRC/g" /home/field/etc/php5/php.ini
然后重启apache
问题解决了,
拓展学习:基于命令的批量修改文件内容
Linux下批量替换多个文件中的字符串的简单方法。用sed命令可以批量替换多个文件中的字符串。
用sed命令可以批量替换多个文件中的字符串。
sed -i "s/原字符串/新字符串/g" `grep 原字符串 -rl 所在目录`(千万注意这个符号,是最左上角那个符号不是单引号)
例如:我要把/test下所有包含abc的文件中的abc替换为def,执行命令:
sed -i "s/abc/def/g" `grep abc -rl /test`
这是目前linux最简单的批量替换字符串命令了!
具体格式如下:
sed -i "s/oldString/newString/g" `grep oldString -rl /path`
实例代码:sed -i "s/大小多少/日月水火/g" `grep 大小多少 -rl /usr/aa`
sed -i "s/大小多少/日月水火/g" `grep 大小多少 -rl ./`
方法2:
在日程的开发过程中,可能大家会遇到将某个变量名修改为另一个变量名的情况,如果这个变量是一个局部变量的话,vi足以胜任,但是如果是某个全局变量的话,并且在很多文件中进行了使用,这个时候使用vi就是一个不明智的选择。这里给出一个简单的shell命令,可以一次性将所有文件中的指定字符串进行修改:
grep "abc" * -R | awk -F: '{print $1}' | sort | uniq | xargs sed -i 's/abc/abcde/g'
替换字符:sed -i "s/old/new/g" /test
查找包含指定字符的文件名:grep aaa –ul /test
#Linux
http://hi.baidu.com/liu731/item/cd5c31e215a10bacc00d7571
http://www.cnblogs.com/txw1958/archive/2012/07/26/linux-pmap.html