`
jingfengluo
  • 浏览: 44423 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Apache模块开发/用C语言扩展apache(2:APR编程介绍)

阅读更多
Apache模块开发/用C语言扩展apache(2:APR编程介绍) by linux_prog 可以看到apache代码中使用了大量的以apr_开头的结构或者函数,这些其实是APR. 什么是apr 我的理解是apache工作小组在编写apache等C程序过程中所积累的一套编程框架,里面提供比较先进的内存管理模式 和常用的数据结构,另外根据各种平台作了一些不同的宏定义,让代码做到平台无关性。由于做得不错,后来,就干脆把它从apache源代码中脱离出来,又搞了一个项目,apache官方站点上也有它的相关介绍:http://apr.apache.org/ The mission of the Apache Portable Runtime (APR) project is to create and maintain software libraries that provide a predictable and consistent interface to underlying platform-specific implementations. The primary goal is to provide an API to which software developers may code and be assured of predictable if not identical behaviour regardless of the platform on which their software is built, relieving them of the need to code special-case conditions to work around or take advantage of platform-specific deficiencies or features. apr可以独立于apache安装,让我们编写应用程序时也使用。 有个非常好的英文文档介绍了怎么样使用:http://dev.ariel-networks.com/apr/apr-tutorial/html/apr-tutorial.html 上面那个文档非常不错,大家看懂了,我写的这篇就不用看了。 我这个把几个以后经常要用到的介绍一下。 (1) apr_pool_t *pool; 内存池,所有的内存操作可以基于这个池之上,当这个池不再需要时,一次性释放该池上的所有内存,这个模式非常适合基于 session服务的编程模式,比如:每个http request都分配一个apr_pool_t,当该http request end时,一次性释放该request运行时申请的所有内存。可以看到struct request_rec中就有这个东东。 用法: apr_pool_t *mp; /* create a memory pool. */ apr_pool_create(&mp, NULL); /* allocate memory chunks from the memory pool */ char *buf1; buf1 = apr_palloc(mp, MEM_ALLOC_SIZE); /* sample code about apr_pool_clear() */ apr_pool_t *mp; apr_pool_create(&mp, NULL); for (i = 0; i < n; ++i) { do_operation(..., mp); apr_pool_clear(mp); } apr_pool_destroy(mp); (2)数据结构--容器 动态数组---apr_array_header_t 类似于hashmap的apr_table_t: apr_table_t *tab; tab = apr_table_make(mp, 5); apr_table_setn(tab, "foo", "bar"); /* string literals don't require duplication */ apr_table_setn(tab, apr_pstrdup(mp, "foo"), apr_pstrdup(mp, "bar")); const char *v = apr_table_get(tab, "mykey"); 可以看到apr_table_t存储key-value pairs类型的数据非常方便,难怪apache所有的http header都用它存储。 其他操作apr_table_t的函数: /** * Get the elements from a table * @param t The table * @return An array containing the contents of the table */ APR_DECLARE(const apr_array_header_t *) apr_table_elts(const apr_table_t *t); /** * Determine if the table is empty * @param t The table to check * @return True if empty, False otherwise */ APR_DECLARE(int) apr_is_empty_table(const apr_table_t *t); /** * Determine if the array is empty * @param a The array to check * @return True if empty, False otherwise */ APR_DECLARE(int) apr_is_empty_array(const apr_array_header_t *a); /** * Create an array * @param p The pool to allocate the memory out of * @param nelts the number of elements in the initial array * @param elt_size The size of each element in the array. * @return The new array */ APR_DECLARE(apr_array_header_t *) apr_array_make(apr_pool_t *p, int nelts, int elt_size); /** * Add a new element to an array (as a first-in, last-out stack) * @param arr The array to add an element to. * @return Location for the new element in the array. * @remark If there are no free spots in the array, then this function will * allocate new space for the new element. */ APR_DECLARE(void *) apr_array_push(apr_array_header_t *arr); /** * Remove an element from an array (as a first-in, last-out stack) * @param arr The array to remove an element from. * @return Location of the element in the array. * @remark If there are no elements in the array, NULL is returned. */ APR_DECLARE(void *) apr_array_pop(apr_array_header_t *arr); /** * Concatenate two arrays together * @param dst The destination array, and the one to go first in the combined * array * @param src The source array to add to the destination array */ APR_DECLARE(void) apr_array_cat(apr_array_header_t *dst, const apr_array_header_t *src); /** * Copy the entire array * @param p The pool to allocate the copy of the array out of * @param arr The array to copy * @return An exact copy of the array passed in * @remark The alternate apr_array_copy_hdr copies only the header, and arranges * for the elements to be copied if (and only if) the code subsequently * does a push or arraycat. */ APR_DECLARE(apr_array_header_t *) apr_array_copy(apr_pool_t *p, const apr_array_header_t *arr); /** * Copy the headers of the array, and arrange for the elements to be copied if * and only if the code subsequently does a push or arraycat. * @param p The pool to allocate the copy of the array out of * @param arr The array to copy * @return An exact copy of the array passed in * @remark The alternate apr_array_copy copies the *entire* array. */ APR_DECLARE(apr_array_header_t *) apr_array_copy_hdr(apr_pool_t *p, const apr_array_header_t *arr); /** * Append one array to the end of another, creating a new array in the process. * @param p The pool to allocate the new array out of * @param first The array to put first in the new array. * @param second The array to put second in the new array. * @return A new array containing the data from the two arrays passed in. */ APR_DECLARE(apr_array_header_t *) apr_array_append(apr_pool_t *p, const apr_array_header_t *first, const apr_array_header_t *second); /** * Generates a new string from the apr_pool_t containing the concatenated * sequence of substrings referenced as elements within the array. The string * will be empty if all substrings are empty or null, or if there are no * elements in the array. If sep is non-NUL, it will be inserted between * elements as a separator. * @param p The pool to allocate the string out of * @param arr The array to generate the string from * @param sep The separator to use * @return A string containing all of the data in the array. */ APR_DECLARE(char *) apr_array_pstrcat(apr_pool_t *p, const apr_array_header_t *arr, const char sep); /** * Make a new table * @param p The pool to allocate the pool out of * @param nelts The number of elements in the initial table. * @return The new table. * @warning This table can only store text data */ APR_DECLARE(apr_table_t *) apr_table_make(apr_pool_t *p, int nelts); /** * Create a new table and copy another table into it * @param p The pool to allocate the new table out of * @param t The table to copy * @return A copy of the table passed in */ APR_DECLARE(apr_table_t *) apr_table_copy(apr_pool_t *p, const apr_table_t *t); /** * Delete all of the elements from a table * @param t The table to clear */ APR_DECLARE(void) apr_table_clear(apr_table_t *t); /** * Get the value associated with a given key from the table. After this call, * The data is still in the table * @param t The table to search for the key * @param key The key to search for * @return The value associated with the key, or NULL if the key does not exist. */ APR_DECLARE(const char *) apr_table_get(const apr_table_t *t, const char *key); /** * Add a key/value pair to a table, if another element already exists with the * same key, this will over-write the old data. * @param t The table to add the data to. * @param key The key fo use * @param val The value to add * @remark When adding data, this function makes a copy of both the key and the * value. */ APR_DECLARE(void) apr_table_set(apr_table_t *t, const char *key, const char *val); /** * Add a key/value pair to a table, if another element already exists with the * same key, this will over-write the old data. * @param t The table to add the data to. * @param key The key to use * @param val The value to add * @warning When adding data, this function does not make a copy of the key or * the value, so care should be taken to ensure that the values will * not change after they have been added.. */ APR_DECLARE(void) apr_table_setn(apr_table_t *t, const char *key, const char *val); /** * Remove data from the table * @param t The table to remove data from * @param key The key of the data being removed */ APR_DECLARE(void) apr_table_unset(apr_table_t *t, const char *key); /** * Add data to a table by merging the value with data that has already been * stored * @param t The table to search for the data * @param key The key to merge data for * @param val The data to add * @remark If the key is not found, then this function acts like apr_table_add */ APR_DECLARE(void) apr_table_merge(apr_table_t *t, const char *key, const char *val); /** * Add data to a table by merging the value with data that has already been * stored * @param t The table to search for the data * @param key The key to merge data for * @param val The data to add * @remark If the key is not found, then this function acts like apr_table_addn */ APR_DECLARE(void) apr_table_mergen(apr_table_t *t, const char *key, const char *val); /** * Add data to a table, regardless of whether there is another element with the * same key. * @param t The table to add to * @param key The key to use * @param val The value to add. * @remark When adding data, this function makes a copy of both the key and the * value. */ APR_DECLARE(void) apr_table_add(apr_table_t *t, const char *key, const char *val); /** * Add data to a table, regardless of whether there is another element with the * same key. * @param t The table to add to * @param key The key to use * @param val The value to add. * @remark When adding data, this function does not make a copy of the key or the * value, so care should be taken to ensure that the values will not * change after they have been added.. */ APR_DECLARE(void) apr_table_addn(apr_table_t *t, const char *key, const char *val); /** * Merge two tables into one new table * @param p The pool to use for the new table * @param overlay The first table to put in the new table * @param base The table to add at the end of the new table * @return A new table containing all of the data from the two passed in */ APR_DECLARE(apr_table_t *) apr_table_overlay(apr_pool_t *p, const apr_table_t *overlay, const apr_table_t *base); /** * Declaration prototype for the iterator callback function of apr_table_do() * and apr_table_vdo(). * @param rec The data passed as the first argument to apr_table_[v]do() * @param key The key from this iteration of the table * @param value The value from this iteration of the table * @remark Iteration continues while this callback function returns non-zero. * To export the callback function for apr_table_[v]do() it must be declared * in the _NONSTD convention. */ typedef int (apr_table_do_callback_fn_t)(void *rec, const char *key, const char *value); /** * Iterate over a table running the provided function once for every * element in the table. If there is data passed in as a vararg, then the * function is only run on those elements whose key matches something in * the vararg. If the vararg is NULL, then every element is run through the * function. Iteration continues while the function returns non-zero. * @param comp The function to run * @param rec The data to pass as the first argument to the function * @param t The table to iterate over * @param ... The vararg. If this is NULL, then all elements in the table are * run through the function, otherwise only those whose key matches * are run. * @return FALSE if one of the comp() iterations returned zero; TRUE if all * iterations returned non-zero * @see apr_table_do_callback_fn_t */ APR_DECLARE_NONSTD(int) apr_table_do(apr_table_do_callback_fn_t *comp, void *rec, const apr_table_t *t, ...); /** * Iterate over a table running the provided function once for every * element in the table. If there is data passed in as a vararg, then the * function is only run on those element's whose key matches something in * the vararg. If the vararg is NULL, then every element is run through the * function. Iteration continues while the function returns non-zero. * @param comp The function to run * @param rec The data to pass as the first argument to the function * @param t The table to iterate over * @param vp The vararg table. If this is NULL, then all elements in the * table are run through the function, otherwise only those * whose key matches are run. * @return FALSE if one of the comp() iterations returned zero; TRUE if all * iterations returned non-zero * @see apr_table_do_callback_fn_t */ APR_DECLARE(int) apr_table_vdo(apr_table_do_callback_fn_t *comp, void *rec, const apr_table_t *t, va_list vp); /** flag for overlap to use apr_table_setn */ #define APR_OVERLAP_TABLES_SET (0) /** flag for overlap to use apr_table_mergen */ #define APR_OVERLAP_TABLES_MERGE (1) /** * For each element in table b, either use setn or mergen to add the data * to table a. Which method is used is determined by the flags passed in. * @param a The table to add the data to. * @param b The table to iterate over, adding its data to table a * @param flags How to add the table to table a. One of: * APR_OVERLAP_TABLES_SET Use apr_table_setn * APR_OVERLAP_TABLES_MERGE Use apr_table_mergen * @remark This function is highly optimized, and uses less memory and CPU cycles * than a function that just loops through table b calling other functions. */ /** * * Conceptually, apr_table_overlap does this: * * apr_array_header_t *barr = apr_table_elts(b); * apr_table_entry_t *belt = (apr_table_entry_t *)barr->elts; * int i; * * for (i = 0; i < barr->nelts; ++i) { * if (flags & APR_OVERLAP_TABLES_MERGE) { * apr_table_mergen(a, belt[i].key, belt[i].val); * } * else { * apr_table_setn(a, belt[i].key, belt[i].val); * } * } * * Except that it is more efficient (less space and cpu-time) especially * when b has many elements. * * Notice the assumptions on the keys and values in b – they must be * in an ancestor of a’s pool. In practice b and a are usually from * the same pool. * */ APR_DECLARE(void) apr_table_overlap(apr_table_t *a, const apr_table_t *b, unsigned flags); /** * Eliminate redundant entries in a table by either overwriting * or merging duplicates * * @param t Table. * @param flags APR_OVERLAP_TABLES_MERGE to merge, or * APR_OVERLAP_TABLES_SET to overwrite */ APR_DECLARE(void) apr_table_compress(apr_table_t *t, unsigned flags); 其他apr提供的数据结构还有:hash和list,这里不再详述。 (3) 字符串操作 写过C的人都知道,处理字符串是非常头痛的问题,搞不好就内存溢出,apr也提供一些字符串函数,都是基于apr_pool_t, 使用时不用担心内存溢出的问题。 把apr_strings.h贴出来大家一起看看,注释也比较详细,不多说: /** * Do a natural order comparison of two strings. * @param a The first string to compare * @param b The second string to compare * @return Either <0, 0, or >0. If the first string is less than the second * this returns <0, if they are equivalent it returns 0, and if the * first string is greater than second string it retuns >0. */ APR_DECLARE(int) apr_strnatcmp(char const *a, char const *b); /** * Do a natural order comparison of two strings ignoring the case of the * strings. * @param a The first string to compare * @param b The second string to compare * @return Either <0, 0, or >0. If the first string is less than the second * this returns <0, if they are equivalent it returns 0, and if the * first string is greater than second string it retuns >0. */ APR_DECLARE(int) apr_strnatcasecmp(char const *a, char const *b); /** * duplicate a string into memory allocated out of a pool * @param p The pool to allocate out of * @param s The string to duplicate * @return The new string */ APR_DECLARE(char *) apr_pstrdup(apr_pool_t *p, const char *s); /** * Create a null-terminated string by making a copy of a sequence * of characters and appending a null byte * @param p The pool to allocate out of * @param s The block of characters to duplicate * @param n The number of characters to duplicate * @return The new string * @remark This is a faster alternative to apr_pstrndup, for use * when you know that the string being duplicated really * has ’n' or more characters. If the string might contain * fewer characters, use apr_pstrndup. */ APR_DECLARE(char *) apr_pstrmemdup(apr_pool_t *p, const char *s, apr_size_t n); /** * Duplicate at most n characters of a string into memory allocated * out of a pool; the new string will be NUL-terminated * @param p The pool to allocate out of * @param s The string to duplicate * @param n The maximum number of characters to duplicate * @return The new string * @remark The amount of memory allocated from the pool is the length * of the returned string including the NUL terminator */ APR_DECLARE(char *) apr_pstrndup(apr_pool_t *p, const char *s, apr_size_t n); /** * Duplicate a block of memory. * * @param p The pool to allocate from * @param m The memory to duplicate * @param n The number of bytes to duplicate * @return The new block of memory */ APR_DECLARE(void *) apr_pmemdup(apr_pool_t *p, const void *m, apr_size_t n); /** * Concatenate multiple strings, allocating memory out a pool * @param p The pool to allocate out of * @param … The strings to concatenate. The final string must be NULL * @return The new string */ APR_DECLARE_NONSTD(char *) apr_pstrcat(apr_pool_t *p, …); /** * Concatenate multiple strings specified in a writev-style vector * @param p The pool from which to allocate * @param vec The strings to concatenate * @param nvec The number of strings to concatenate * @param nbytes (output) strlen of new string (pass in NULL to omit) * @return The new string */ APR_DECLARE(char *) apr_pstrcatv(apr_pool_t *p, const struct iovec *vec, apr_size_t nvec, apr_size_t *nbytes); /** * printf-style style printing routine. The data is output to a string * allocated from a pool * @param p The pool to allocate out of * @param fmt The format of the string * @param ap The arguments to use while printing the data * @return The new string */ APR_DECLARE(char *) apr_pvsprintf(apr_pool_t *p, const char *fmt, va_list ap); /** * printf-style style printing routine. The data is output to a string * allocated from a pool * @param p The pool to allocate out of * @param fmt The format of the string * @param … The arguments to use while printing the data * @return The new string */ APR_DECLARE_NONSTD(char *) apr_psprintf(apr_pool_t *p, const char *fmt, …) __attribute__((format(printf,2,3))); /** * Copy up to dst_size characters from src to dst; does not copy * past a NUL terminator in src, but always terminates dst with a NUL * regardless. * @param dst The destination string * @param src The source string * @param dst_size The space available in dst; dst always receives * NUL termination, so if src is longer than * dst_size, the actual number of characters copied is * dst_size - 1. * @return Pointer to the NUL terminator of the destination string, dst * @remark * * Note the differences between this function and strncpy(): * 1) strncpy() doesn’t always NUL terminate; apr_cpystrn() does. * 2) strncpy() pads the destination string with NULs, which is often * unnecessary; apr_cpystrn() does not. * 3) strncpy() returns a pointer to the beginning of the dst string; * apr_cpystrn() returns a pointer to the NUL terminator of dst, * to allow a check for truncation. * */ APR_DECLARE(char *) apr_cpystrn(char *dst, const char *src, apr_size_t dst_size); /** * Strip spaces from a string * @param dest The destination string. It is okay to modify the string * in place. Namely dest == src * @param src The string to rid the spaces from. * @return The destination string, dest. */ APR_DECLARE(char *) apr_collapse_spaces(char *dest, const char *src); /** * Convert the arguments to a program from one string to an array of * strings terminated by a NULL pointer * @param arg_str The arguments to convert * @param argv_out Output location. This is a pointer to an array of strings. * @param token_context Pool to use. */ APR_DECLARE(apr_status_t) apr_tokenize_to_argv(const char *arg_str, char ***argv_out, apr_pool_t *token_context); /** * Split a string into separate null-terminated tokens. The tokens are * delimited in the string by one or more characters from the sep * argument. * @param str The string to separate; this should be specified on the * first call to apr_strtok() for a given string, and NULL * on subsequent calls. * @param sep The set of delimiters * @param last Internal state saved by apr_strtok() between calls. * @return The next token from the string */ APR_DECLARE(char *) apr_strtok(char *str, const char *sep, char **last); /** * @defgroup APR_Strings_Snprintf snprintf implementations * @warning * These are snprintf implementations based on apr_vformatter(). * * Note that various standards and implementations disagree on the return * value of snprintf, and side-effects due to %n in the formatting string. * apr_snprintf (and apr_vsnprintf) behaves as follows: * * Process the format string until the entire string is exhausted, or * the buffer fills. If the buffer fills then stop processing immediately * (so no further %n arguments are processed), and return the buffer * length. In all cases the buffer is NUL terminated. It will return the * number of characters inserted into the buffer, not including the * terminating NUL. As a special case, if len is 0, apr_snprintf will * return the number of characters that would have been inserted if * the buffer had been infinite (in this case, *buffer can be NULL) * * In no event does apr_snprintf return a negative number. * @{ */ /** * snprintf routine based on apr_vformatter. This means it understands the * same extensions. * @param buf The buffer to write to * @param len The size of the buffer * @param format The format string * @param … The arguments to use to fill out the format string. */ APR_DECLARE_NONSTD(int) apr_snprintf(char *buf, apr_size_t len, const char *format, …) __attribute__((format(printf,3,4))); /** * vsnprintf routine based on apr_vformatter. This means it understands the * same extensions. * @param buf The buffer to write to * @param len The size of the buffer * @param format The format string * @param ap The arguments to use to fill out the format string. */ APR_DECLARE(int) apr_vsnprintf(char *buf, apr_size_t len, const char *format, va_list ap); /** @} */ /** * create a string representation of an int, allocated from a pool * @param p The pool from which to allocate * @param n The number to format * @return The string representation of the number */ APR_DECLARE(char *) apr_itoa(apr_pool_t *p, int n); /** * create a string representation of a long, allocated from a pool * @param p The pool from which to allocate * @param n The number to format * @return The string representation of the number */ APR_DECLARE(char *) apr_ltoa(apr_pool_t *p, long n); /** * create a string representation of an apr_off_t, allocated from a pool * @param p The pool from which to allocate * @param n The number to format * @return The string representation of the number */ APR_DECLARE(char *) apr_off_t_toa(apr_pool_t *p, apr_off_t n); /** * Convert a numeric string into an apr_off_t numeric value. * @param offset The value of the parsed string. * @param buf The string to parse. It may contain optional whitespace, * followed by an optional ’+' (positive, default) or ’-' (negative) * character, followed by an optional ’0x’ prefix if base is 0 or 16, * followed by numeric digits appropriate for base. * @param end A pointer to the end of the valid character in buf. If * not NULL, it is set to the first invalid character in buf. * @param base A numeric base in the range between 2 and 36 inclusive, * or 0. If base is zero, buf will be treated as base ten unless its * digits are prefixed with ’0x’, in which case it will be treated as * base 16. */ APR_DECLARE(apr_status_t) apr_strtoff(apr_off_t *offset, const char *buf, char **end, int base); /** * parse a numeric string into a 64-bit numeric value * @param buf The string to parse. It may contain optional whitespace, * followed by an optional ’+' (positive, default) or ’-' (negative) * character, followed by an optional ’0x’ prefix if base is 0 or 16, * followed by numeric digits appropriate for base. * @param end A pointer to the end of the valid character in buf. If * not NULL, it is set to the first invalid character in buf. * @param base A numeric base in the range between 2 and 36 inclusive, * or 0. If base is zero, buf will be treated as base ten unless its * digits are prefixed with ’0x’, in which case it will be treated as * base 16. * @return The numeric value of the string. On overflow, errno is set * to ERANGE. */ APR_DECLARE(apr_int64_t) apr_strtoi64(const char *buf, char **end, int base); /** * parse a base-10 numeric string into a 64-bit numeric value. * Equivalent to apr_strtoi64(buf, (char**)NULL, 10). * @param buf The string to parse * @return The numeric value of the string */ APR_DECLARE(apr_int64_t) apr_atoi64(const char *buf); /** * Format a binary size (magnitiudes are 2^10 rather than 10^3) from an apr_off_t, * as bytes, K, M, T, etc, to a four character compacted human readable string. * @param size The size to format * @param buf The 5 byte text buffer (counting the trailing null) * @return The buf passed to apr_strfsize() * @remark All negative sizes report ’ - ’, apr_strfsize only formats positive values. */ APR_DECLARE(char *) apr_strfsize(apr_off_t size, char *buf);
分享到:
评论

相关推荐

    使用json-lib-2.2.2-jdk15.jar所要用到的jar包

    json-lib-2.2.3-jdk15.jar commons-beanutils-1.7.0.jar commons-httpclient-3.1.jar ...要在java里使用json用到的jar包怎么导入?把包粘贴到WebRootWEB-INFlib目录下就行了 不用自己单独建立libs目录

    解决报错java.lang.NoClassDefFoundError: org/apache/james/mime4j/MimeException

    该jar包解决报错java.lang.NoClassDefFoundError: org/apache/james/mime4j/MimeException,亲测可用。

    tomcat7 http://tomcat.apache.org/download-70.cgi

    http://tomcat.apache.org/download-70.cgi http://tomcat.apache.org/download-70.cgi

    webservice启动没有问题,通过自动生成的客户端报错

    at org.apache.axis.message.SOAPFaultBuilder.endElement(SOAPFaultBuilder. java:169) at org.apache.axis.encoding.DeserializationContextImpl.endElement(Deseri alizationContextImpl.java:1015) at ...

    Maven问题:Downloading from central: https://repo1.maven.org/maven2/org/apache/maven/plugins/maven-a

    今天在使用IDEA创建Maven的webapp时遇见这样一个不叫问题的问题: Downloading from central: https://repo1.maven.org/maven2/org/apache/maven/plugins/maven-archetype-plugin/maven-metadata.xml 很奇怪,我的...

    json所有的jar包下载

    json-lib-2.2.3-jdk15.jar commons-beanutils-1.7.0.jar commons-httpclient-3.1.jar commons-lang-2.3.jar commons-logging-1.1.1.jar ...java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory

    使用json所要用到的jar包

    json-lib-2.2.3-jdk15.jar commons-beanutils-1.7.0.jar commons-httpclient-3.1.jar commons-lang-2.3.jar commons-logging-1.1.1.jar ...java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory

    apache模块开发指南(中文版)

    这在很大程度上帮助开发人员克服了C语言编程的缺陷,特别是交叉编译平台和资源管理方面的缺陷。通过使用Apache 2,C程序员可以达到通常被认为是高层次语言和脚本语言才能达到的高效率。 新的拓展架构带来了全新层次...

    Apache模块开发

    Apache模块开发指南

    Apache模块开发指南

    《LAMP技术精品书廊•Apache模块开发指南》主要介绍了Apache模块开发的全过程。全面细致、深入浅出,主要内容包括Apache相关背景、APR的基础知识,以及利用Apache模块开发的全过程,适合广大在Apache环境下的模块...

    apache 模块开发的例子

    apache可以通过扩展它的模块来实现自定义功能,apache 模块开发的例子,欢迎交流。

    APACHE模块开发指南

    apache模块开发指南,汉语版,很辛苦找到的。

    Apache2.2中文文档电子书(PDF+在线版)

    Apache服务器模块介绍 Apache服务器开发者文档 Apache服务器在其他平台的使用 常见问题 在线版文档:http://doc.zzbaike.com/apache/2-2/ PDF电子书: http://doc.zzbaike.com/apache/book/apache2.2.pdf 如果要...

    apache 采用C语言的模块开发

    我在改造APACHE服务器授权访问时,需要对不合法的客户端请求进行过滤。对不合法请求需要立即发送一个错误提示页面给客户端。 发送错误提示页面的程序片断如下: //非法请求作错误跳转 char *location...

    window环境下apache模块开发工具apxs及安装使用详细说明

    自己在项目开发中用到的apache模块开发工具apxs,重要的是这个工具在windows环境下的安装方法和使用方法,非常珍贵,泣血推荐

    apr-1.7.0.zip

    2、apr-1.7.0.tar 报错: rm: cannot remove `libtoolT': No such file or directory 解决: configure中#$RM "$cfgfile" 3、apr-util-1.6.1.tar 报错: fatal error:expat.h:no such file or directory  #...

    apache-maven-3.5.0-bin

    2) A directory called "apache-maven-3.x.y" will be created. 3) Add the bin directory to your PATH, e.g.: Unix-based operating systems (Linux, Solaris and Mac OS X) export PATH=/usr/local/apache-...

    apache模块开发入门

    学习apache模块开发的基础学习文档,非常好用。

    apr-util-1.6.1.zip

    2、apr-1.7.0.tar 报错: rm: cannot remove `libtoolT': No such file or directory 解决: configure中#$RM "$cfgfile" 3、apr-util-1.6.1.tar 报错: fatal error:expat.h:no such file or directory  #...

    Apache APR可移植运行库 Win32

    http://apache.mirror.phpchina.com/apr/apr-1.3.3-win32-src.zip http://apache.mirror.phpchina.com/apr/apr-util-1.3.4-win32-src.zip http://apache.mirror.phpchina.com/apr/apr-iconv-1.2.1-win32-src.zip

Global site tag (gtag.js) - Google Analytics