Part 1 : Writing PHP Extension

My friend Rama Yurindra from Zend told me that he wants to drive PHP (on Windows) together with us. Everybody knows that PHP already works on IIS since from beginning, so what make it is so attractive to me? The new FastCGI is cool, but I believe we can do more attractive stuffs to value PHP developers in Windows world.
Microsoft-Zend collaboration is started by Sam Ramji who runs Open Source Lab at Microsoft. He has hundreds of physical and virtual servers running 40+ distributions of Linux, 12+ variant of Unix, and several versions of Windows. Sam Ramji leads some interesting research projects including testing interoperability of network protocols like IPSEC and IPv6 between Linux and and Windows technology, the user experience and technical capabilities of HPC projects like ROCKS and Ganglia. SQL Server team also started to provide SQL Server Driver for PHP. You can download it here.
I was thinking to enable huge # of PHP developers and Websites in Indonesia to take advantages from Microsoft investments on Web technologies. Let say, Windows Live, AJAX, Silverlight, Infocard, Windows HPC, etc. A lot of cool stuffs (Live ID, IM, Virtual Earth, Parallel/Concurrency stuffs) nowadays we can bring as extensions to PHP. Isn't that interesting ?? Of course yes ! And actually I had initial conversation with my friend Angus Logan to start work on PHP Extension for Windows Live.
My goal in this article is to encourage Indonesian developers to start working on non-LOB (line of business) applications and start playing in the international play ground. Yes, I really want to see that happen and PHP extension is just one work item in my plan. It means, we have to back to C++ native world again (this time not for molecular dynamic simulation). For you who want to follow my C++ journey, I will send you my collection of C++ How Do I videos in DVD if you put your shipping address in this blog as comment. Let start by writing simple PHP Extension first, then we can brainstorm more on writing extension for Windows Live.
1. Preparation for Your 1st PHP Extension
- Download and install Visual C++ 2008 (express edition is okay)
- Windows Vista Platform SDK (will be included in DVD)
- Windows Vista SP1 with IIS 7.0
- Install PHP 5.x.x in Windows Vista & IIS 7.0 (FastCGI/ISAPI/CGI)
- Download and extract PHP 5 Source Codes in PHP-DEV directory
- Download Zend Framework and Its documentation. I use Zend Framework 1.5.2.
Note : If you done with all of those steps, you are ready !
2. Understand PHP Internals
If you are not getting PHP internal knowledge (once you dive into a working extension it should make sense to understand), I recommend you read PHP manual first then consult to Sara Golemon and Black Schwendiman books. Some resources from Edin blogs and Sara article are also useful.
Every PHP developers should familiar with extensions. You can find the list of extensions in PHP.INI file. Most of PHP functions are part of the standard extension - not in the PHP core itself. The PHP source bundle comes with around 86 extensions, the PECL repository offers over 100 additional extensions.
How PHP Works in IIS ?
Lets think PHP as two core subsystems : Zend Engine (ZE) and PHP Core Engine (PCE). ZE handles parsing a PHP script into machine-readable tokens, and then executing those tokens within a process space. ZE also handles memory management, variable scope, and dispatching function calls. PCE handles communication with, and bindings to, the SAPI handlers (Server Application Programming Interface). PCE also provides a unified control layer for safe_mode and open_basedir checks, as well as the streams layer which associates file and network I/O with user-space functions like fopen(), fread(), and fwrite().
IIS 7.0 implemented an integrated pipeline architecture to manage all HTTP requests coming from kernel mode listerner (HTTP.SYS). The latest module before an HTTP request reach the SAPI handler is execute_handler who will dispatch HTTP request to its proper handler module. IIS 7.0 provides three SAPI handler modules for PHP: CGI (cgi.dll), ISAPI (isapi.dll) and FastCGI (iisfcgi.dll) modules. I strongly suggest you to understand internal architecture of each handler to match your hosting requirement. In IIS 7.0, you can check your IIS configuration file (applicationHost.config) to check whether you have all of those SAPI handler modules exist or not.
<add name="FastCgiModule" image="%windir%\System32\inetsrv\iisfcgi.dll" />
<add name="IsapiModule" image="%windir%\System32\inetsrv\isapi.dll" />
<add name="CgiModule" image="%windir%\System32\inetsrv\cgi.dll" />
Each IIS SAPI module handler will communicate to its associated PHP Core Subsystems (php-win.exe, php-cgi.exe, php5isapi.dll) through TCP or named pipes. When a given IIS SAPI handler starts-up to handle HTTP request, PHP begins by initializing its core subsystems (ZE and PCE). Towards the end of this startup routine, it loads the code for each extension and calls their Module Initialization routine (MINIT). This gives each extension a chance to initialize internal variables, allocate resources, register resource handlers, and register its functions with ZE, so that if a script calls one of those functions, ZE knows which code to execute.

Next, PHP waits for the SAPI handler module to request a page to be processed. In the case of the CGI, ISAPI or FastCGI handler module in IIS. This happens immediately and only once and all request are queued before being processed. No matter how the request comes in, PHP begins by asking ZE to setup an environment for the script to run in, then calls each extension's Request Initialization (RINIT) function. RINIT gives the extension a chance to set up specific environment variables, allocate request specific resources, or perform other tasks such as auditing. Once the request is initialized by RINIT, ZE takes over by translating the PHP script into tokens, and finally to opcodes which it can step through and execute. Should one of these opcodes requires an extension function to be called, ZE will bundle up the arguments for that function, and temporarily give over control until it completes.
After a script has finished executing, PHP calls the Request Shutdown (RSHUTDOWN) function of each extension to perform any last minute cleanup (such as saving session variables to disk). Next, ZE performs a cleanup process (known as garbage collection) which effectively performs an unset() on every variable used during the previous request.

Once completed, PHP waits for IIS SAPI handler module to either request another document or signal a shutdown. In the case of the CGI, there is no "next request" because each HTTP request invokes exactly one OS process, so the SAPI initiates a shutdown immediately. During shutdown, PHP again cycles through each extension calling their Module Shutdown (MSHUTDOWN) functions, and finally shuts down its own core subsystems. ISAPI and FastCGI has different mechanism in handling HTTP request. CGI is too costly in IIS because OS process creation in Windows is expensive comparing to thread creation. FastCGI improves the CGI mechanism by allowing reuse of an OS process, while ISAPI is loaded as extension to IIS worker process.
In order to avoid losing memory to poorly written extensions, PHP-ZE performs its own internal memory management using an additional flag that indicates persistence, lets called it Zend Memory Management (ZendMM) layer. This portion of ZendMM acts in much the same way the operating system would normally act, allocating memory to calling applications. The difference is that it is low enough in the process space to be request-aware so that when one request dies, it can perform the same action the OS would perform when a process dies. That is, it implicitly frees all the memory owned by that request.
A persistent allocation in ZendMM is a memory allocation that is meant to last for longer than a single page request. A non-persistent allocation, by contrast, is freed at the end of the request in which it was allocated, whether or not the free function is called. User-space PHP variables, for example, are allocated non-persistently because at the end of a request they're no longer useful. While an extension may, in theory, rely on ZE to free non-persistent memory automatically at the end of each page request, this is not recommended. Memory allocations will remain un-reclaimed for longer periods of time, resources associated with that memory will be less likely to be shutdown properly, and it's just poor practice to make a mess without cleaning it up.
So.... when we are going to write our 1st PHP extension? I am a fans of bottom-up learning and I think it is important for you to understand the internal of PHP before writing extension codes. We will start to write codes in Part 2.
Hope this helps !!
Ciao - RAM