注:LINUX菜鸟一个,本博文摘录自各网站自己整理而成!欢迎各位大神评论指导!



进程和线程:

进程:一个程序对一个数据集的动态执行过程,是分配资源的基本单位。 

线程: 一个进程内的基本调度单位。

进程与线程的一个简单解释

进程(process)和线程(thread)是操作系统的基本概念,但是它们比较抽象,不容易掌握。

最近,我读到一篇材料,发现有一个很好的类比,可以把它们解释地清晰易懂。

1.

bg2013042401.jpg

计算机的核心是CPU,它承担了所有的计算任务。它就像一座工厂,时刻在运行。

2.

bg2013042402.png

假定工厂的电力有限,一次只能供给一个车间使用。也就是说,一个车间开工的时候,其他车间都必须停工。背后的含义就是,单个CPU一次只能运行一个任务。

3.

bg2013042403.jpg

进程就好比工厂的车间,它代表CPU所能处理的单个任务。任一时刻,CPU总是运行一个进程,其他进程处于非运行状态。

4.

bg2013042404.jpg

一个车间里,可以有很多工人。他们协同完成一个任务。

5.

bg2013042405.jpg

线程就好比车间里的工人。一个进程可以包括多个线程。

6.

bg2013042406.png

车间的空间是工人们共享的,比如许多房间是每个工人都可以进出的。这象征一个进程的内存空间是共享的,每个线程都可以使用这些共享内存。

7.

bg2013042407.jpg

可是,每间房间的大小不同,有些房间最多只能容纳一个人,比如厕所。里面有人的时候,其他人就不能进去了。这代表一个线程使用某些共享内存时,其他线程必须等它结束,才能使用这一块内存。

8.

bg2013042408.jpg

一个防止他人进入的简单方法,就是门口加一把锁。先到的人锁上门,后到的人看到上锁,就在门口排队,等锁打开再进去。这就叫"互斥锁"(Mutual exclusion,缩写 Mutex),防止多个线程同时读写某一块内存区域。

9.

bg2013042409.jpg

还有些房间,可以同时容纳n个人,比如厨房。也就是说,如果人数大于n,多出来的人只能在外面等着。这好比某些内存区域,只能供给固定数目的线程使用。

10.

bg2013042410.jpg

这时的解决方法,就是在门口挂n把钥匙。进去的人就取一把钥匙,出来时再把钥匙挂回原处。后到的人发现钥匙架空了,就知道必须在门口排队等着了。这种做法叫做"信号量"(Semaphore),用来保证多个线程不会互相冲突。

不难看出,mutex是semaphore的一种特殊情况(n=1时)。也就是说,完全可以用后者替代前者。但是,因为mutex较为简单,且效率高,所以在必须保证资源独占的情况下,还是采用这种设计。

11.

bg2013042411.png

操作系统的设计,因此可以归结为三点:

(1)以多进程形式,允许多个任务同时运行;

(2)以多线程形式,允许单个任务分成不同的部分运行;

(3)提供协调机制,一方面防止进程之间和线程之间产生冲突,另一方面允许进程之间和线程之间共享资源。

(完)




Apache两种模式:

prefork模式

这个多路处理模块(MPM)实现了一个非线程型的、预派生的web服务器,它的工作方式类似于Apache 1.3。它适合于没有线程安全库,需要避免线程兼容性问题的系统。它是要求将每个请求相互独立的情况下最好的MPM,这样若一个请求出现问题就不会影响到其他请求。

这个MPM具有很强的自我调节能力,只需要很少的配置指令调整。最重要的是将MaxClients设置为一个足够大的数值以处理潜在的请求高峰,同时又不能太大,以致需要使用的内存超出物理内存的大小。

worker模式

此多路处理模块(MPM)使网络服务器支持混合的多线程多进程。由于使用线程来处理请求,所以可以处理海量请求,而系统资源的开销小于基于进程的MPM。但是,它也使用了多进程,每个进程又有多个线程,以获得基于进程的MPM的稳定性。

控制这个MPM的最重要的指令是,控制每个子进程允许建立的线程数的ThreadsPerChild指令,和控制允许建立的总线程数的MaxClients指令。

prefork和worker模式的切换

1.将当前的prefork模式启动文件改名

mv httpd httpd.prefork

2.将worker模式的启动文件改名

mv httpd.worker httpd

3.修改Apache配置文件

vi /usr/local/apache2/conf/extra/httpd-mpm.conf

找到里边的如下一段,可适当修改负载等参数:

<IfModule mpm_worker_module>

StartServers 2

MaxClients 150

MinSpareThreads 25

MaxSpareThreads 75

ThreadsPerChild 25

MaxRequestsPerChild 0

</IfModule>

4.重新启动服务

/usr/local/apache2/bin/apachectl restart

即可换成worker方式启动apache2

处于稳定性和安全性考虑,不建议更换apache2的运行方式,使用系统默认prefork即可。另外很多php模块不能工作在worker模式下,例如redhat linux自带的php也不能支持线程安全。所以最好不要切换工作模式。

prefork和worker模式的比较

prefork模式使用多个子进程,每个子进程只有一个线程。每个进程在某个确定的时间只能维持一个连接。在大多数平台上,Prefork MPM在效率上要比Worker MPM要高,但是内存使用大得多。prefork的无线程设计在某些情况下将比worker更有优势:它可以使用那些没有处理好线程安全的第三方模块,并 且对于那些线程调试困难的平台而言,它也更容易调试一些。

worker模式使用多个子进程,每个子进程有多个线程。每个线程在某个确定的时间只能维持一个连接。通常来说,在一个高流量的HTTP服务器 上,Worker MPM是个比较好的选择,因为Worker MPM的内存使用比Prefork MPM要低得多。但worker MPM也由不完善的地方,如果一个线程崩溃,整个进程就会连同其所有线程一起”死掉”.由于线程共享内存空间,所以一个程序在运行时必须被系统识别为”每 个线程都是安全的”。

总的来说,prefork方式速度要稍高于worker,然而它需要的cpu和memory资源也稍多于woker。

prefork模式配置详解

<IfModule mpm_prefork_module>

ServerLimit 256

StartServers 5

MinSpareServers 5

MaxSpareServers 10

MaxClients 256

MaxRequestsPerChild 0

</IfModule>

ServerLimit

默认的MaxClient最大是256个线程,如果想设置更大的值,就的加上ServerLimit这个参数。20000是ServerLimit这个参数的最大值。如果需要更大,则必须编译apache,此前都是不需要重新编译Apache。

生效前提:必须放在其他指令的前面

StartServers

指定服务器启动时建立的子进程数量,prefork默认为5。

MinSpareServers

指定空闲子进程的最小数量,默认为5。如果当前空闲子进程数少于MinSpareServers ,那么Apache将以最大每秒一个的速度产生新的子进程。此参数不要设的太大。

MaxSpareServers

设置空闲子进程的最大数量,默认为10。如果当前有超过MaxSpareServers数量的空闲子进程,那么父进程将杀死多余的子进程。此参数不要设的 太大。如果你将该指令的值设置为比MinSpareServers小,Apache将会自动将其修改成”MinSpareServers+1″。

MaxClients

限定同一时间客户端最大接入请求的数量(单个进程并发线程数),默认为256。任何超过MaxClients限制的请求都将进入等候队列,一旦一个链接被释放,队列中的请求将得到服务。要增大这个值,你必须同时增大ServerLimit。

MaxRequestsPerChild

每个子进程在其生存期内允许伺服的最大请求数量,默认为10000.到达MaxRequestsPerChild的限制后,子进程将会结束。如果 MaxRequestsPerChild为”0″,子进程将永远不会结束。将MaxRequestsPerChild设置成非零值有两个好处:

1.可以防止(偶然的)内存泄漏无限进行,从而耗尽内存。

2.给进程一个有限寿命,从而有助于当服务器负载减轻的时候减少活动进程的数量。

worker模式配置详解

<IfModule mpm_worker_module>

StartServers 2

MaxClients 150

MinSpareThreads 25

MaxSpareThreads 75

ThreadsPerChild 25

MaxRequestsPerChild 0

</IfModule>

StartServers

服务器启动时建立的子进程数,默认值是”3″。

MaxClients

允许同时伺服的最大接入请求数量(最大线程数量)。任何超过MaxClients限制的请求都将进入等候队列。默认值是”400″ ,16(ServerLimit)乘以25(ThreadsPerChild)的结果。因此要增加MaxClients的时候,你必须同时增加 ServerLimit的值。

MinSpareThreads

最小空闲线程数,默认值是”75″。这个MPM将基于整个服务器监视空闲线程数。如果服务器中总的空闲线程数太少,子进程将产生新的空闲线程。

MaxSpareThreads

设置最大空闲线程数。默认值是”250″。这个MPM将基于整个服务器监视空闲线程数。如果服务器中总的空闲线程数太多,子进程将杀死多余的空闲线程。 MaxSpareThreads的取值范围是有限制的。Apache将按照如下限制自动修正你设置的值:worker要求其大于等于 MinSpareThreads加上ThreadsPerChild的和。

ThreadsPerChild

每个子进程建立的常驻的执行线程数。默认值是25。子进程在启动时建立这些线程后就不再建立新的线程了。

MaxRequestsPerChild

设置每个子进程在其生存期内允许伺服的最大请求数量。到达MaxRequestsPerChild的限制后,子进程将会结束。如果MaxRequestsPerChild为”0″,子进程将永远不会结束。将MaxRequestsPerChild设置成非零值有两个好处:

1.可以防止(偶然的)内存泄漏无限进行,从而耗尽内存。

2.给进程一个有限寿命,从而有助于当服务器负载减轻的时候减少活动进程的数量。

注意对于KeepAlive链接,只有第一个请求会被计数。事实上,它改变了每个子进程限制最大链接数量的行为。




apache学习笔记【转载】

源码安装apache2.0,DSO(动态加载模块方式),也是通常安装方式:
$./configure --prefix=/usr/local/apache2s --with-layout=Apache --enable-modules-most --enable-mods-share=all
$make
$make install
*************************************************************
安装第三方模块:
/path/to/apache/bin/apxs -cia module.c
-c(compile)编译
-i(install)安装
-a(activate)启动
对于只有一个.c文件的模块,可以用这个命令安装,如果是有多个源码文件的模块,则需要其本身的安装说明
*************************************************************
安装mod_perl
$cd mod_perl_2.0.2/
$perl Makefile.PL USE_APXS=1 WITH_APXS=/usr/local/apache2s/bin/apxs EVERYTHING=1 PERL_USELARGEFILES=0
$make
$make install
然后:
将LoadModule perl_module modules/mod_perl.so这句话加入到httpd.conf文件中,重启apache
检查:
$/usr/local/apache2s/bin/apxs -q LIBEXECDIR   显示模块所在目录(例如:/usr/local/apache2/modules)
*************************************************************
安装php模块:
$cd php-4.4.4/
$./configure --with-apxs=/usr/local/apache2/bin/apxs (apache1.3) 
或$./configure --with-apxs2=/usr/local/apache2/bin/apxs (apache2.X)
$make
$make install
修改配置文件,添加:
LoadModule php4_module modules/libphp4.so

AddType application/x-httpd-php .php .php3 .any_file_in_php
AddHandler application/x-httpd-php .php .php3 .any_file_in_php
这样这台服务器的php网页就可以正常访问了!
*************************************************************
日志格式中状态码内容,详见PaoloDocuments/apache/http协议规范文件RFC2616.txt
*************************************************************
指定日志记录格式,组合日志格式(combined)或通用日志格式(common),修改配置文件:
CustomLog logs/access_log combined    组合日志格式
CustomLog logs/access_log common      通用日志格式
*************************************************************
LogLevel 配置文件中的这个指令指定日志记录等级(但无论指定什么记录等级,日志都会记录notice等级的信息)
*************************************************************
通用日志格式与组合日志格式的"%h"控制符表示远程请求用户的身份,依据HostNameLookups指令的设定值,可能是主机名也可能是IP地址。如果想永远记录IP地址,则使用“%a”控制符
*************************************************************
记录从客户端收到的cookie
CustomLog logs/cookies_in.log "%{UNIQUE_ID}e %{Cookie}i"
CustomLog logs/cookies2_in.log "%{UNIQUE_ID}e %{Cookie2}i"
记录由服务器设定并传送给客户端的cookie值:
CustomLog logs/cookies_out.log "%{UNIQUE_ID}e %{Set-Cookie}o"
CustomLog logs/cookies2_out.log "%{UNIQUE_ID}e %{Set-Cookie2}o"
*************************************************************
不记录来自本机网页的图像请求:

SetEnvIfNoCase Referrer "^http://www.example.com/" local_referrer=1

Customlog logs/access_log combined env=!local_referrer
*************************************************************
按照日或小时来记录请求:
CustomLog "| /usr/local/apache2/bin/rotatelogs /usr/local/apache2/logs/access_log.%Y-%m-%d 86400" combined
其中:
rotatelogs的第一个参数是主日志文件名如果有%字符,则表示日志文件名中时间的格式,如果没有指定时间格式,则是以秒为单位,从1970.1.1日算起的秒数
            第二个参数是产生新日志的间隔是多少秒。也可以是大小如果把上例中的86400换成5M,则表时日志达到5M时,就会产生一个新的日志,日志的名字是access_log.%Y-%m-%d格式的
参阅:man -M /usr/local/apache2/man rotatelogs.8
*************************************************************
logresolve 将日志中记录的IP地址解析为主机名
例如:
$logresolve -c < /usr/local/apache2/logs/access_log.raw > access_log.resolved
也可以让apache在处理过程中使用IP地址,然后在记录日志时,以管道方式的日志记录进程来解析,修改配置文件:
HostnameLookups off
CustomLog "|/usr/local/apache2/bin/logresolve -c >> /usr/local/apache2/logs/access_log.resolved" combined
*************************************************************
只有一个IP,但想在系统上支持多个网站:
NameVirtualHost *

    ServerAdmin webmaster@dummy-host.example.com
    DocumentRoot /www/docs/dummy-host.example.com
    ServerName dummy-host.example.com
    ServerAlias 
www.paolo.com                    ######p这条指令可对虚拟主机设定多个名称
    ErrorLog logs/dummy-host.example.com-error_log
    CustomLog logs/dummy-host.example.com-access_log common

其中:"*"表示所设定的主机可在所有的地址上运行。对于只有单一地址的机器,这表示会在该地址上运行,同时也会在loopback地址上运行。
如果NameVirtualHost 后面放置主机名称可能会在启动服务器时停用虚拟主机的机制。
虚拟主机会使用户无法再访问配置文件中的主服务器。如果想让主服务器成为默认服务器,则必须在虚拟主机区块中先将它列出。
对于每个虚拟主机名称,还需要在DNS中添加相关记录。
*************************************************************
$/usr/local/apache2/bin/httpd -S    显示虚拟主机的配置
*************************************************************
ErrorDocument 404 /err.html    这个指令可以让没有打到指定网页的时候,不显示404错误,而是err.html页面。错误号可以是其它的号码,如403、500等

例如:

    ServerAdmin webmaster@dummy-host.example.com
    DocumentRoot /www/docs/wangqi.paolo.com
    ServerName wangqi.paolo.com
    ErrorLog logs/wangqi.paolo.com-error_log
    CustomLog logs/wangqi.paolo.com-access_log combined
    ErrorDocument 404 /err.html

根据以上配置,访问wangqi.paolo.com/index.html时,如果/www/docs/wangqi.paolo.com目录下没有index.html文件时,则会显示/www/docs/wangqi.paolo.com目录下的err.html文件
*************************************************************
如果是有多个IP的情况下,想在每个地址上支持一个网站:
NameVirtualHost 127.0.0.1

    ServerAdmin webmaster@dummy-host.example.com
    DocumentRoot /www/docs/paolo.paolo.com
    ServerName paolo.paolo.com
    ErrorLog logs/paolo.paolo.com-error_log
    CustomLog logs/paolo.paolo.com-access_log combined


    ServerAdmin webmaster@dummy-host.example.com
    DocumentRoot /www/docs/cissy.paolo.com
    ServerName cissy.paolo.com
    ErrorLog logs/cissy.paolo.com-error_log
    CustomLog logs/cissy.paolo.com-access_log combined

以上配置根据所访问的IP地址不同,会访问不同的虚拟主机。如果服务器上还有其它的IP地址,但是没有在配置文件的虚拟主机区块列出来时,这时访问这个其它的IP地址,请求会被送至在配置文件主设定区的虚拟主机
*************************************************************
建立以IP寻址的默认虚拟主机,以配置文件中加入下面代码:

    DocumentRoot /www/htdocs
    ErrorDocument 404 /err.html

加入以上代码后,如果访问本地的IP,但是该IP确没有在配置文件中配置时,则会访问以上代码指定的页面
*************************************************************
混用以IP寻址及以名称寻址虚拟主机:
ServerName 127.0.0.1
NameVirtualHost 10.4.5.135
NameVirtualHost 10.4.5.230
                       ################此处不同
    ServerAdmin 
webmaster@dummy-host.example.com
    DocumentRoot /www/docs/cissy.paolo.com
    ServerName cissy.paolo.com                 ################此处不同
    ErrorLog logs/cissy.paolo.com-error_log
    CustomLog logs/cissy.paolo.com-access_log combined

                          ################此处不同
    ServerAdmin 
webmaster@dummy-host.example.com
    DocumentRoot /www/docs/cissy.paolo.com
    ServerName wangqi.paolo.com                          ################此处不同
    ErrorLog logs/wangqi.paolo.com-error_log
    CustomLog logs/wangqi.paolo.com-access_log combined

                          ################此处不同
    ServerAdmin 
webmaster@dummy-host.example.com
    DocumentRoot /www/docs/cissy.paolo.com
    ServerName paolo.paolo.com                          ################此处不同
    ErrorLog logs/paolo.paolo.com-error_log
    CustomLog logs/paolo.paolo.com-access_log combined

*************************************************************
mod_vhost_alias   模块可以建立大量的虚拟主机
*************************************************************
将URL对应至特定目录。也就是说,如果我们访问
http://10.4.5.135/paolo,我们如果不想让他访问/usr/local/apache2/htdocs/paolo,而是让它访问其它的目录中的内容,我们可以在配置文件中加入如下:
Alias /paolo /home/paolo/apache_paolo

然后还要把指定的目录加入到配置文件中,以让apache可以访问,默认情况下apache是不访问DocumentRoot以外的目录的。

    Order allow,deny
    Allow from all

这种用Alias的目录指定,其实是用Alias的第二个参数去替换第一个参数。本例中就是用/home/paolo/apache_paolo去替换/paolo,因此,我们访问http://10.4.5.135/paolo,其实上是访问http://10.4.5.135/home/paolo/apache_paolo
这种方法对"/"符号要求非常严格,如果上例我们写成Alias /paolo/ /home/paolo/apache_paolo,而我们在访问http://10.4.5.135/paolo/index.html,其实是访问http://10.4.5.135/home/paolo/apache_paoloindex.html,这是错误的,因为/home/paolo/apache_paolo替换的是/paolo/,注意,这里把最后的“/”也替换了,所以转换后就是前面所说那样错误的URL。

Alias也可以为现有的网页内容创建新的URL,例如要想原来http://10.4.5.135/php/phpinfo.php内容,通过http://10.4.5.135/newphp/phpinfo.php也可以访问,只要在配置文件中加入如下一行:
  Alias /newphp /usr/local/apache2/htdocs/php

Alias只影响本地URI,不会影响URL的主机名部分
*************************************************************
让服务器的用户都有自己的URL,有自己的网页空间,配置文件:
UserDir public_html      
配置文件中有这行指令后,再在用户主目录下创建public_html目录,里面放入网页就可以了。访问的URL为,以wangqi这个用户为例:
http://10.4.5.135/~wangqi/
还要将配置文件中一段注释去掉:
#

#    AllowOverride FileInfo AuthConfig Limit Indexes
#    Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
#    

#        Order allow,deny
#        Allow from all
#    

#    
#        Order deny,allow
#        Deny from all
#    

#
以配置访问权限。

另一种方式:
UserDir /www/user/*/htdocs
这种方法后的参数是完整的路径名,把用户的页面文件都放在了统一的目录下(/www/usr/下),后面的*号是用户名命名的目录。访问方法和上面第一种方法一样
*************************************************************
AliasMatch ^/testph(p|ps) /usr/local/apache2/htdocs/php
用AliasMatch指令,可以用正则表达式的方式将多个URL对应至同一个目录,以上指令,可以用:
http://10.4.5.135/testphp/phpinfo.php
http://10.4.5.135/testphps/phpinfo.php来访问同一个目录中的内容
*************************************************************
重定向至其他URL,修改配置文件:
Redirect /sohu 
http://www.sohu.com
以上指令访问http:10.4.5.135/sohu时,实际访问的是http://www.sohu.com
Redirect指令有几个参数:
temp:表示文件当前不在原来所请求的位置上,可以将来还会在这个位置上,现在只是临时的。这样,客户端会记住原始请求的URL。
permanent:表示被请求的文件不在指定位置上,而是永久在新的位置上。这样,客户端会记住新的URL
gone:表示文件不在此位置,而且以后也不在新的位置上。相当于404错误。但服务器会承认所请求的文件原来在此位置。所以不会被视为错误。
seeother:表示文件不在所请求的位置,而且被不同位置的其它文件取代了(前三个参数都是指同一个文件,这个参数请是不同位置的不同文件取代了原来位置的原来文件)
默认情况下是使用temp参数

用RedirectMatch指令可以用正则表达式的方式将多个URL重定向至同一位置。具体用法详见前面AliasMatch的用法
*************************************************************
接受不区分大小写的URL:
1.安装mod_speling模块
2.在配置文件中添加:
 CheckSpelling On
*************************************************************
mod_rewrite模块可以重写URL请求中的文件,替换成指定的;可以拒绝访问未被引用的请求;可以依据查询字符串来重写;可以将所有请求重定向是单一主机;将服务器的全部或部分请求重定向至SSL等相关工作
具体用法详见《apache经典实例》,比较复杂,不写了!
*************************************************************
使用系统帐号在web上进行身份验证:
在配置文件中在想要控制的文件目录的领域下:

AuthType Basic
AuthName HomeDir
AuthUserFile /etc/passwd
Require valid-user
Satisfy All

注意,由于/etc/passwd的文件格式和htpasswd管理的文件格式是一样的,所以我们才可以用/etc/passwd进行身份验证,不过我们现在的linux系统都采用/etc/shadow文件来存储密码,所以就无法用这种方式进行身份验证了。这时我们登录网页,虽然会提示我们输入用户名和密码,但永远无法正确通过验证
所以此方法已不再适用,除非改成用/etc/passwd存放用户密码
*************************************************************
在子目录中放宽安全限制
也就是说,比如我们现在已经在/usr/local/apache2/htdocs/这个目录上加上了用户名和密码的认证。但我们想在/usr/local/apache2/htdocs/php这个目录中不需要认证,使用户可以直接访问
要达到上面的要求我们可以这样,在配置文件中加入:

Satisfy Any
Order Deny,Allow
Allow from all

或者:
在/usr/local/apache2/htdocs/php目录下建立.htaccess文件,把
Satisfy Any
Order Deny,Allow
Allow from all
这三行内容写在.htaccess文件里面。
*************************************************************
如果已经限制了一个目录的访问,需要用户名和密码,但想要放开这个目录中的其中一个文件(例如:back.html)的权限,使其可以任意访问,在配置文件中添加:

Satisfy Any
Order Deny,Allow
Allow from all

*************************************************************
查看通过验证的用户名称:
可以查看REMOTE_USER环境变更。在access_log中也可以看到。
*************************************************************
禁止通过代理服务器访问特定的URL,修改配置文件:
ProxyBlock .rm .ra .mp3


Order Allow,Deny
Deny from all
Satisfy All

上述方法都无法满足要求时,可以使用正则表达式的方式,使用Rewrite指令。
*************************************************************
想拒绝所有对目录中文件的访问,除了特殊指定扩展名的文件(比如.html文件):

Satisfy all
Order Allow,Deny
Deny from all
        

          Order Deny,Allow
          Allow from all
          Satisfy any
        

以上指令,使得test目录及其子目录下的所有非.html文件无法访问,只有.html的文件可以访问
*************************************************************
ab -n 1000 -c 20 
http://10.4.5.135/back.html      测试apache性能的工具
其中:
-n 1000 表示请求的数目
-c 20 表示一次送出20 个请求
-h 可以查看帮助
*************************************************************
取得网站快照,修改配置文件:

    SetHandler server-status
#    Order deny,allow
#    Deny from all
#    Allow from .example.com

ExtendedStatus On
*************************************************************
将经常查看的文件存入高速缓存区,修改配置文件:
MMapFile /usr/local/apache2/htdocs/index.html              需要安装mod_file_cache模块
*************************************************************
将目录列表存入高速缓存区,修改配置文件:
IndexOptions +TrackModified
*************************************************************
*************************************************************
*************************************************************
*************************************************************
*************************************************************