📄 1272.html
字号:
<br>
上面的写法是利用 C 的前置编译器做处理,如果在编译时加入 -DFASTCGI 的参数则引入 fcgi_stdio.h ,反之则否。假设我们把 fcgi_stdio.h 标头文件放在 /usr/local/include/fastcgi 这个目录下的话,为了在编译时引入 fcgi_stdio.h 标头档,请加入 -I/usr/local/include/fastcgi 的参数。<br>
<br>
$ cc -I/usr/local/include/fastcgi -c program.c<br>
<br>
注意<br>
如果你的程序使用到其它的函式库,请务必检查这些函式库是否有使用到 stdio.h 这个档,如果有的话必须一并换成 fcgi_stdio.h。举例来说,假如你的程序用到 GD 函式库4来产生 GIF 图形,请记得把 gd.h 中引入 stdio.h 的部份换成 fcgi_stdio.h,否则遇到 IO 的函式时会发生错误 (Core Dump)。<br>
<br>
3.3 FastCGI 处理循环<br>
在 FastCGI 程序中负责处理联机请求的程序,必须用一个 while 循环包起来,利用 fcgi_stdio 函式库中的 FCGI_Accept() 函式库来判断是否有新的联机请求发生。<br>
<br>
FastCGI 程序被激活后,首先进行初始化的动作,如变量宣告、内存配置、或是与数据库建立联机等。执行到 FCGI_Accept() 时程序就会暂停,等到当某一个联机请求发生时,FCGI_Accept() 会传回大于零的值,程序即刻进入循环的主体,可能是执行 SQL 指令,运算以及产生 HTML 的输出。处理完后又回到 FCGI_Accept() 循环的开始,等待下一个联机请求。<br>
<br>
由此可见, FastCGI 激活之后,省去原本 CGI 程序中 fork,内存配置,建立数据库联机等步骤,处理每个联机请求的时间几乎等于 FCGI_Accept() 这个循环中运算所需的时间。如果妥善将每次联机请求时一样的程序代码从 FCGI_Accept() 循环抽出来,只保留每次会产生不同结果的部份,则程序处理每次联机请求的时间可以更短,整个网站的效率也可以大幅的提升。<br>
<br>
了解 FastCGI 程序的基本架构后,可以发现一般的 CGI 程序,只要加入 FCGI_Accept() 这个 while 循环后,大概就可以变成 FastCGI 的程序了。<br>
<br>
3.4 炼结 libfcgi.a 函式库<br>
FastCGI 程序要炼结到 libfcgi.a 函式库才可正确产生出执行档,假设 libfcgi.a 的位置在 /usr/local/lib 这个目录下,我们在编译 (炼结时) 要加入 -L/usr/local/lib -lfcgi 的参数。<br>
<br>
<br>
$ cc -o program.fcg program.o -L/usr/local/lib -lfcgi<br>
<br>
3.5 撰写 FastCGI 程序的注意事项<br>
由于 FastCGI 程序被激活后就常驻在内存之中,对每个 FastCGI 的执行行程 (running process) 而言,每次联机请求共享的变量空间是相同的,因些选写 FastCGI 程序要特别留意一些注意事项。<br>
<br>
1. 记住,对每个 FastCGI 程序而言,只有 FCGI_Accept() 循环内的程序才是真正处理每次联机请求的主体,假设在程序中要读取和 CGI 有关的环境变量,或是使用者透过窗体 (form) 所输入的资料,必须在 FCGI_Accept() 循环内才处理。<br>
2. 对每次联机请求会改变的变量,别忘了在处理新的联机请求前把变量初始化 (除非是有特殊用途) ,以避免变量值在不同的联机请求之间互相影响。<br>
3. 在 FCGI_Accept() 循环中配置 (allocate) 的内存别忘了释放 (free)。在一般的 CGI 程序中, Memory Leak 不算是太大的问题,因为每处理完一次联机请求,所有用到的内存随着 CGI 程序的结束也被释放。但是 FastCGI 程序会一直常驻在内存中,如果在 FCGI_Accept() 中有配置额外的内存,在循环结束前没有释放掉,则每处理一次联机请求就吃掉一些系统的内存,多跑几次下来,系统资源大概就被耗光了。Memory leak 的问题是 FastCGI 最常见的错误,要特别小心处理。<br>
4. FastCGI 程序和其所要引用的子程序中,用到 stdio.h 函式的部份,记得要改成 fcgi_stdio.h 。否则当程序在遇到 IO 的动作时就会发生 Core Dump 的情况。<br>
5. 在 FCGI_Accept() 循环中使用 FCGI_Finish() 函式以取代 exit() 函式。原本 CGI 程序中发生错误时,可能直接呼叫 exit() 函式结束 CGI 行程,FastCGI 程序也可以如此,因为 mod_fastcgi 模块在 FastCGI 程序发生错误而意外结束时,会自动再激活另一个 FastCGI 的行程。但比较好的作法是呼叫 fcgi_stdio.h 中的 FCGI_Finish() 函式,呼叫 FCGI_Finish() 函式会跳出目前程序正在运算中的循环,回到 FCGI_Accept() 等待下一个联机请求。如此可以省去一些网站服务器激活新的 FastCGI 行程的负担。<br>
<br>
----------------------------------------------------------------------------<br>
<br>
4. FastCGI 有多快?<br>
<br>
看完安装 FastCGI 的阿帕契模块,以及无聊的程序设计注意事项后,我们来看看一些可以让人振奋精神的数据,效能比较 (bench mark) 总是计算机玩家的最爱 icon_smile.gif<br>
<br>
4.1 评比工具 - ApacheBench<br>
在阿帕契服务器的套件中,有一个叫做 ab (ApacheBench) 的工具。ApacheBench 主要是用来测试阿帕契服务器执行效率用的,我们就以 ApacheBench 做为 CGI vs. FastCGI 的评比工具。<br>
<br>
ApacheBench 可以针对某个特定的 URL 仿真出连续的联机请求,同时还可以仿真出同时间点数个相同的联机请求,因此利用 ApacheBench 可帮助我们在网站开发期间仿真实际上线可能的情况,利用仿真出来的数据做为调整服务器设定或程序的依据。 ApacheBench 的用法如下:<br>
<br>
Usage: /usr/local/apache/bin/ab [options] [http://]hostname[:port]/path<br>
Options are:<br>
-n requests Number of requests to perform<br>
-c concurrency Number of multiple requests to make<br>
-t timelimit Seconds to max. wait for responses<br>
-p postfile File containg data to POST<br>
-T content-type Content-type header for POSTing<br>
-v verbosity How much troubleshooting info to print<br>
-w Print out results in HTML tables<br>
-x attributes String to insert as table attributes<br>
-y attributes String to insert as tr attributes<br>
-z attributes String to insert as td or th attributes<br>
-V Print version number and exit<br>
-k Use HTTP KeepAlive feature<br>
-h Display usage information (this message)<br>
<br>
假设我们要对 echo.fcg 做测试,仿真 1000 次的联机请求,而且同一时间有 20 个并行的 (concurrent) 联机请求的情况,只要在命令列模式下执行<br>
<br>
$ ab -n 1000 -c 20 http://localhost/fcgi-bin/echo.fcg<br>
稍等一会,ApacheBench 会把结果秀出来,<br>
<br>
This is ApacheBench, Version 1.3<br>
Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/<br>
Copyright (c) 1998-1999 The Apache Group, http://www.apache.org/<br>
<br>
Benchmarking localhost (be patient)... Server Software: Apache/1.3.6<br>
Server Hostname: localhost<br>
Server Port: 80<br>
Document Path: /fcgi-bin/echo.fcg<br>
Document Length: 995 bytes<br>
Concurrency Level: 20<br>
Time taken for tests: 6.859 seconds<br>
Complete requests: 1000<br>
Failed requests: 0<br>
Total transferred: 1142000 bytes<br>
HTML transferred: 995000 bytes<br>
Requests per second: 145.79<br>
Transfer rate: 166.50 kb/s received<br>
<br>
Connnection Times (ms)<br>
min avg max<br>
<br>
Connect: 0 4 61<br>
Processing: 62 128 771<br>
Total: 62 132 832<br>
<br>
以上结果指出,在同时间 20 个联机请求 (Concurrency Level) 的情况下,完成 1000 次的联机请求,共花了 6.859 秒 (Time taken for tests),因此这个程序每秒平均可以处理 (Requests per second) 145.79 个联机请求。<br>
在接下来的评比测试中,我们就以每秒可以处理的联机请求数目来做为效能评比的依据。<br>
<br>
4.2 CGI vs. FastCGI<br>
前面提过利用 fcgi_stdio.h 函式库编译出来的 FastCGI 程序也兼容于 CGI 模式,因此我们只要把 fcgi-devkit-2.1 套件附的范例程序 echo.fcg 复制到 /cgi-bin 目录下,并且把文件名改成 echo.cgi,这支范例程序就可分别以 CGI 模式和 FastCGI 模式来执行,并且做比较。<br>
<br>
首先分别对 CGI模式执行的 http://localhost/cgi-bin/echo.cgi 以及 FastCGI 模式的 http://localhost/fcgi-bin/echo.fcg 连续送出 10, 100, 1000, 10000 次的联机请求,得到的平均每秒可处理的请求 (Requests per second) 结果为:<br>
<br>
联机数目 10 100 1000 10000<br>
CGI 52.63 53.08 52.24 51.49<br>
FastCGI (static mode) 204.08 224.22 146.78 207.14<br>
<br>
接下来再分别以 Concurrency Level 为 10, 50, 100 的情况下做测试,得到 Requests per second 结果为:<br>
<br>
Concurrency 联机数目 10 100 1000 10000<br>
10 CGI 38.31 46.55 53.61 55.09<br>
10 FastCGI 185.19 208.33 162.63 177.14<br>
50 CGI 27.25 33.16 50.72 53.99<br>
50 FastCGI 92.59 176.37 196.58 196.88<br>
100 CGI 17.92 24.84 48.14 52.84<br>
100 FastCGI 86.21 187.27 195.54 193.17<br>
<br>
由上述数据看来,对同一支程序 (echo.c) 而言,使用 FastCGI 模式来执行,速度提升了 3-4 倍。可见得 FastCGI 对网站程序的效能提升上具有相当大的助益,尤其当使用量很大时,其效益更加明显。<br>
<br>
以上的测试条件并不是十分严谨,主要在让你了解使用 FastCGI 之后对于效能及速度上一个概括的比较,也提供一个可供网站开发者可以评量的依据。<br>
<br>
实际上,对一个初始化动作复杂,例如要先和数据库建立联机,或是配置内存,做变量初始化的程序来说,使用 FastCGI 可以比原先 CGI 在效能上增加更多,速度更快。而对一个有数据库可联机数目限制的系统来说,使用 FastCGI 就好象一个 Application Server 一样,不用担心 CGI 一次 fork 太多,超过联机数目上限 (FastCGI 可以设定一次跑几支)。<br>
<br>
4.3 找出 Memory Leak<br>
善用 ApacheBench 这个工具,还可以帮助网站程序发展人员找出在 FastCGI 程序中隐藏的 Memory Leak 臭虫。<br>
<br>
每一支 FastCGI 程序在处理完一个联机请求后的状况都应该相同,我们利用 ApacheBench 对欲测试的程序送出上百次或上千次的联机请求以仿真实际上线的状况,如果发现程序占用的内存愈来愈多而且不会减少的话,表示程序有 Memory Leak 的问题。<br>
<br>
虽然对 FastCGI 程序而言,当它一直不断吃掉系统资源到资料耗尽后会自动退出 (core dump 或是 exit) ,释放所占用的资源然后再重新激活,但这将会影响系统其它功能的正常运作,所以撰写 FastCGI 程序一定特别小心。<br>
<br>
----------------------------------------------------------------------------<br>
<br>
5. 参考<br>
如果你想更进一步了解 FastCGI ,在 FastCGI 的首页上可以找到相关的所有资料,包含 FastCGI 的发展规格,软件下载,说明文件等。FastCGI 首页的网址是 http://www.fastcgi.com/<br>
<br>
FastCGI 也有一个邮件讨论区 (mailing list),你可以寄 email 至<br>
fastcgi-developers-request@idle.com<br>
在邮件的主旨 (Subject) 处填上 subscribe 即可。但是在发问之前,请先把说明文件或安装文件看清楚,或是到邮件讨论区的档案 (mail archive) 中先找找问题是否已经有人问过而且有人回答过了,以免浪费重复的网络资源。如果你发现了 mod_fastcgi 模块或 fcgi-devkit 发展套件的错误或严重的问题,FastCGI 的发展小组会很热心的帮你想办法解决。<br>
FastCGI 还有许多不同的用法,以及特别的应用,就有待您亲自去探索了。希望本文能帮助有心使用 FastCGI 的朋友可以顺利地安装 FastCGI 相关模块和程序,让你的网站都能全速前进。<br>
<br>
摘自:http://linuxfab.cx<br>
</FONT><br>
</TD>
</TR>
<TR>
<TD colSpan=2><FONT
class=middlefont></FONT><BR>
<FONT
class=normalfont>全文结束</FONT> </TD>
</TR>
<TR>
<TD background="images/dot.gif" tppabs="http://www.linuxhero.com/docs/images/dot.gif" colSpan=2
height=10></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE></DIV></TD>
<TD vAlign=top width="20%"
background="images/line.gif" tppabs="http://www.linuxhero.com/docs/images/line.gif" rowSpan=2>
<DIV align=center>
<table class=tableoutline cellspacing=1 cellpadding=4
width="100%" align=center border=0>
<tr class=firstalt>
<td noWrap background="images/bgline.gif" tppabs="http://www.linuxhero.com/docs/images/bgline.gif" colspan=2 height=21>
<font class=normalfont><b>所有分类</b></font></td>
</tr>
<tr class=secondalt> <td noWrap width=27%> <font class=normalfont>1:</font> </td><td noWrap width=73%> <table width=100% border=0> <tr> <td><font class=normalfont><a href="type1.html" tppabs="http://www.linuxhero.com/docs/type1.html">非技术类</a></font></td> </tr> </table></td></tr><tr class=firstalt> <td noWrap width=27%> <font class=normalfont>2:</font> </td><td noWrap width=73%> <table width=100% border=0> <tr> <td><font class=normalfont><a href="type2.html" tppabs="http://www.linuxhero.com/docs/type2.html">基础知识</a></font></td> </tr> </table></td></tr><tr class=secondalt> <td noWrap width=27%> <font class=normalfont>3:</font> </td><td noWrap width=73%> <table width=100% border=0> <tr> <td><font class=normalfont><a href="type3.html" tppabs="http://www.linuxhero.com/docs/type3.html">指令大全</a></font></td> </tr> </table></td></tr><tr class=firstalt> <td noWrap width=27%> <font class=normalfont>4:</font> </td><td noWrap width=73%> <table width=100% border=0> <tr> <td><font class=normalfont><a href="type4.html" tppabs="http://www.linuxhero.com/docs/type4.html">shell</a></font></td> </tr> </table></td></tr><tr class=secondalt> <td noWrap width=27%> <font class=normalfont>5:</font> </td><td noWrap width=73%> <table width=100% border=0> <tr> <td><font class=normalfont><a href="type5.html" tppabs="http://www.linuxhero.com/docs/type5.html">安装启动</a></font></td> </tr> </table></td></tr><tr class=firstalt> <td noWrap width=27%> <font class=normalfont>6:</font> </td><td noWrap width=73%> <table width=100% border=0> <tr> <td><font class=normalfont><a href="type6.html" tppabs="http://www.linuxhero.com/docs/type6.html">xwindow</a></font></td> </tr> </table></td></tr><tr class=secondalt> <td noWrap width=27%> <font class=normalfont>7:</font> </td><td noWrap width=73%> <table width=100% border=0> <tr> <td><font class=normalfont><a href="type7.html" tppabs="http://www.linuxhero.com/docs/type7.html">kde</a></font></td> </tr> </table></td></tr><tr class=firstalt> <td noWrap width=27%> <font class=normalfont>8:</font> </td><td noWrap width=73%> <table width=100% border=0> <tr> <td><font class=normalfont><a href="type8.html" tppabs="http://www.linuxhero.com/docs/type8.html">gnome</a></font></td> </tr> </table></td></tr><tr class=secondalt> <td noWrap width=27%> <font class=normalfont>9:</font> </td><td noWrap width=73%> <table width=100% border=0> <tr> <td><font class=normalfont><a href="type9.html" tppabs="http://www.linuxhero.com/docs/type9.html">输入法类</a></font></td> </tr> </table></td></tr><tr class=firstalt> <td noWrap width=27%> <font class=normalfont>10:</font> </td><td noWrap width=73%> <table width=100% border=0> <tr> <td><font class=normalfont><a href="type10.html" tppabs="http://www.linuxhero.com/docs/type10.html">美化汉化</a></font></td> </tr> </table></td></tr><tr class=secondalt> <td noWrap width=27%> <font class=normalfont>11:</font> </td><td noWrap width=73%> <table width=100% border=0> <tr> <td><font class=normalfont><a href="type11.html" tppabs="http://www.linuxhero.com/docs/type11.html">网络配置</a></font></td> </tr> </table></td></tr><tr class=firstalt> <td noWrap width=27%> <font class=normalfont>12:</font> </td><td noWrap width=73%> <table width=100% border=0> <tr> <td><font class=normalfont><a href="type12.html" tppabs="http://www.linuxhero.com/docs/type12.html">存储备份</a></font></td> </tr> </table></td></tr><tr class=secondalt> <td noWrap width=27%> <font class=normalfont>13:</font> </td><td noWrap width=73%> <table width=100% border=0> <tr> <td><font class=normalfont><a href="type13.html" tppabs="http://www.linuxhero.com/docs/type13.html">杂项工具</a></font></td> </tr> </table></td></tr><tr class=firstalt> <td noWrap width=27%> <font class=normalfont>14:</font> </td><td noWrap width=73%> <table width=100% border=0> <tr> <td><font class=normalfont><a href="type14.html" tppabs="http://www.linuxhero.com/docs/type14.html">编程技术</a></font></td> </tr> </table></td></tr><tr class=secondalt> <td noWrap width=27%> <font class=normalfont>15:</font> </td><td noWrap width=73%> <table width=100% border=0> <tr> <td><font class=normalfont><a href="type15.html" tppabs="http://www.linuxhero.com/docs/type15.html">网络安全</a></font></td> </tr> </table></td></tr><tr class=firstalt> <td noWrap width=27%> <font class=normalfont>16:</font> </td><td noWrap width=73%> <table width=100% border=0> <tr> <td><font class=normalfont><a href="type16.html" tppabs="http://www.linuxhero.com/docs/type16.html">内核技术</a></font></td> </tr> </table></td></tr><tr class=secondalt> <td noWrap width=27%> <font class=normalfont>17:</font> </td><td noWrap width=73%> <table width=100% border=0> <tr> <td><font class=normalfont><a href="type17.html" tppabs="http://www.linuxhero.com/docs/type17.html">速度优化</a></font></td> </tr> </table></td></tr><tr class=firstalt> <td noWrap width=27%> <font class=normalfont>18:</font> </td><td noWrap width=73%> <table width=100% border=0> <tr> <td><font class=normalfont><a href="type18.html" tppabs="http://www.linuxhero.com/docs/type18.html">apache</a></font></td> </tr> </table></td></tr><tr class=secondalt> <td noWrap width=27%> <font class=normalfont>19:</font> </td><td noWrap width=73%> <table width=100% border=0> <tr> <td><font class=normalfont><a href="type19.html" tppabs="http://www.linuxhero.com/docs/type19.html">email</a></font></td> </tr> </table></td></tr><tr class=firstalt> <td noWrap width=27%> <font class=normalfont>20:</font> </td><td noWrap width=73%> <table width=100% border=0> <tr> <td><font class=normalfont><a href="type20.html" tppabs="http://www.linuxhero.com/docs/type20.html">ftp服务</a></font></td> </tr> </table></td></tr><tr class=secondalt> <td noWrap width=27%> <font class=normalfont>21:</font> </td><td noWrap width=73%> <table width=100% border=0> <tr> <td><font class=normalfont><a href="type21.html" tppabs="http://www.linuxhero.com/docs/type21.html">cvs服务</a></font></td> </tr> </table></td></tr><tr class=firstalt> <td noWrap width=27%> <font class=normalfont>22:</font> </td><td noWrap width=73%> <table width=100% border=0> <tr> <td><font class=normalfont><a href="type22.html" tppabs="http://www.linuxhero.com/docs/type22.html">代理服务</a></font></td> </tr> </table></td></tr><tr class=secondalt> <td noWrap width=27%> <font class=normalfont>23:</font> </td><td noWrap width=73%> <table width=100% border=0> <tr> <td><font class=normalfont><a href="type23.html" tppabs="http://www.linuxhero.com/docs/type23.html">samba</a></font></td> </tr> </table></td></tr><tr class=firstalt> <td noWrap width=27%> <font class=normalfont>24:</font> </td><td noWrap width=73%> <table width=100% border=0> <tr> <td><font class=normalfont><a href="type24.html" tppabs="http://www.linuxhero.com/docs/type24.html">域名服务</a></font></td> </tr> </table></td></tr><tr class=secondalt> <td noWrap width=27%> <font class=normalfont>25:</font> </td><td noWrap width=73%> <table width=100% border=0> <tr> <td><font class=normalfont><a href="type25.html" tppabs="http://www.linuxhero.com/docs/type25.html">网络过滤</a></font></td> </tr> </table></td></tr><tr class=firstalt> <td noWrap width=27%> <font class=normalfont>26:</font> </td><td noWrap width=73%> <table width=100% border=0> <tr> <td><font class=normalfont><a href="type26.html" tppabs="http://www.linuxhero.com/docs/type26.html">其他服务</a></font></td> </tr> </table></td></tr><tr class=secondalt> <td noWrap width=27%> <font class=normalfont>27:</font> </td><td noWrap width=73%> <table width=100% border=0> <tr> <td><font class=normalfont><a href="type27.html" tppabs="http://www.linuxhero.com/docs/type27.html">nfs</a></font></td> </tr> </table></td></tr><tr class=firstalt> <td noWrap width=27%> <font class=normalfont>28:</font> </td><td noWrap width=73%> <table width=100% border=0> <tr> <td><font class=normalfont><a href="type28.html" tppabs="http://www.linuxhero.com/docs/type28.html">oracle</a></font></td> </tr> </table></td></tr><tr class=secondalt> <td noWrap width=27%> <font class=normalfont>29:</font> </td><td noWrap width=73%> <table width=100% border=0> <tr> <td><font class=normalfont><a href="type29.html" tppabs="http://www.linuxhero.com/docs/type29.html">dhcp</a></font></td> </tr> </table></td></tr><tr class=firstalt> <td noWrap width=27%> <font class=normalfont>30:</font> </td><td noWrap width=73%> <table width=100% border=0> <tr> <td><font class=normalfont><a href="type30.html" tppabs="http://www.linuxhero.com/docs/type30.html">mysql</a></font></td> </tr> </table></td></tr><tr class=secondalt> <td noWrap width=27%> <font class=normalfont>31:</font> </td><td noWrap width=73%> <table width=100% border=0> <tr> <td><font class=normalfont><a href="type31.html" tppabs="http://www.linuxhero.com/docs/type31.html">php</a></font></td> </tr> </table></td></tr><tr class=firstalt> <td noWrap width=27%> <font class=normalfont>32:</font> </td><td noWrap width=73%> <table width=100% border=0> <tr> <td><font class=normalfont><a href="type32.html" tppabs="http://www.linuxhero.com/docs/type32.html">ldap</a></font></td> </tr> </table></td></tr> </table>
</DIV></TD></TR>
<TR vAlign=top>
<TD width="80%">
<DIV align=center><BR>
</DIV>
</TD></TR></TBODY></TABLE></TD></TR>
</TABLE></TD></TR>
</TABLE>
<TABLE cellSpacing=0 cellPadding=4 width="100%" bgColor=#eeeeee
border=0><TBODY>
<TR>
<TD width="50%">
<P><FONT class=middlefont>版权所有 © 2004 <A
href="mailto:bjchenxu@sina.com">linux知识宝库</A><BR>
违者必究. </FONT></P>
</TD>
<TD width="50%">
<DIV align=right><FONT class=middlefont>Powered by: <A
href="mailto:bjchenxu@sina.com">Linux知识宝库</A> Version 0.9.0 </FONT></DIV>
</TD></TR></TBODY></TABLE>
<CENTER></CENTER></TD></TR>
</TABLE></CENTER></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -