Chinaunix

标题: lighttpd-1.4.20源码分析[更新于2009-05-20 在第66楼] [打印本页]

作者: lenky0401    时间: 2009-02-13 19:10
标题: lighttpd-1.4.20源码分析[更新于2009-05-20 在第66楼]
lighttpd-1.4.20源码看了很久了,学习总结本来早就该写了的,只是人懒得很,拖拖拉拉到现在,如果各位看了觉得多少还有那么一点点帮助,我就继续来(当然,总结的东东还是会发在这个帖子内)。

预计总共将有15个左右PDF文件发上来 谢谢各位支持

各基本数据结构的分析整理倒是基本完了 但是lighttpd源码最核心的东西(比如配置信息的加载 比如对客户请求访问的响应 等) 我还没整理完 呵呵
未完 请继续关注



[更新于2009-05-20 在第66楼]

[ 本帖最后由 lenky0401 于 2009-5-20 00:32 编辑 ]

lighttpd-1.4.20源码分析之lighttpd主工作模型.pdf

217.26 KB, 下载次数: 8102

lighttpd-1.4.20源码分析之伸展树.pdf

891.86 KB, 下载次数: 5060

lighttpd-1.4.20源码分析之数据结构.pdf

87.14 KB, 下载次数: 4421

lighttpd-1.4.20源码分析之Array.c源码分析.pdf

79.1 KB, 下载次数: 3879

lighttpd-1.4.20源码分析之Etag.c源码分析.pdf

84.87 KB, 下载次数: 3711

lighttpd-1.4.20源码分析之Stat_cache.c源码分析.pdf

109.04 KB, 下载次数: 3744

lighttpd-1.4.20源码分析之Chunk.c源码分析.pdf

71.7 KB, 下载次数: 3886

lighttpd-1.4.20源码分析之Bitset.c源码分析.pdf

64.08 KB, 下载次数: 3472

lighttpd-1.4.20源码分析之Buffer.c源码分析.pdf

83.73 KB, 下载次数: 4299


作者: kunis    时间: 2009-02-13 19:13
多谢lz哈~~~,下来看看。。。
作者: langue    时间: 2009-02-13 19:22
有点意思。不如就这样写下去吧,以后的更新也发到这个帖。
作者: nicksean    时间: 2009-02-13 19:49
多谢lz 下来看看。。。
作者: lenky0401    时间: 2009-02-13 20:49
原帖由 langue 于 2009-2-13 19:22 发表
有点意思。不如就这样写下去吧,以后的更新也发到这个帖。


多谢langue帮我扎起,和大家一起学习,我对lighttpd源码也还有不少部分理解起来成问题。
作者: xinglp    时间: 2009-02-13 21:10
支持
作者: kestre1    时间: 2009-02-13 21:17
文档看了一遍,顶LZ~
作者: lenky0401    时间: 2009-02-13 22:10
原帖由 kestre1 于 2009-2-13 21:17 发表
文档看了一遍,顶LZ~


谢谢 预计将有15个PDF文件发上来 请关注
作者: converse    时间: 2009-02-13 23:05
支持。
结合项目阅读代码是提高编程能力的捷径之一。
作者: Roemer    时间: 2009-02-13 23:10
UP
作者: lenky0401    时间: 2009-02-13 23:13
原帖由 converse 于 2009-2-13 23:05 发表
支持。
结合项目阅读代码是提高编程能力的捷径之一。


converse 你好,多谢你之前的热心帮助。
作者: converse    时间: 2009-02-13 23:58
标题: 回复 #11 lenky0401 的帖子
很高兴我的付出对你能有帮助!

作者: kyle000    时间: 2009-02-14 11:32
收下了慢慢研读
作者: 3227049    时间: 2009-02-14 11:40
MARK下
作者: boywonder    时间: 2009-02-14 22:44
非常感谢!!!
作者: lenky0401    时间: 2009-02-14 23:10
谢谢LS几位 如果看了 有疑问 请跟帖 和大家一起讨论
作者: vbs100    时间: 2009-02-15 17:06
我也是看到converse 的文章才关注这个代码的 感谢两位出色的分析
作者: ggff112    时间: 2009-02-15 23:04
等收齐了,好好读读,毕竟我刚学,也许对我有帮助
作者: lenky0401    时间: 2009-02-15 23:54
:wink: 嗯

[ 本帖最后由 lenky0401 于 2009-2-15 23:57 编辑 ]
作者: Sorehead    时间: 2009-02-16 17:23
支持一下
作者: penguin_vip    时间: 2009-02-16 23:35
原帖由 lenky0401 于 2009-2-13 19:10 发表
lighttpd-1.4.20源码看了很久了,学习总结本来早就该写了的,只是人懒得很,拖拖拉拉到现在,如果各位看了觉得多少还有那么一点点帮助,我就继续来(当然,总结的东东还是会发在这个帖子内)。

预计 ...

有没有使用方法,编译、调试能,那样学习效果更好!!!
作者: lenky0401    时间: 2009-02-17 09:31
原帖由 penguin_vip 于 2009-2-16 23:35 发表

有没有使用方法,编译、调试能,那样学习效果更好!!!



我在看配置信息解析加载的时候 自己实际修改 编译 调试过
你是说 需要把如何修改 编译 调式 写个总结么?

那个和所有linux下程序编译是一样的
作者: dreamice    时间: 2009-02-17 10:17
感谢分享
作者: FreeB_U    时间: 2009-02-18 13:18
太厉害了。。谢谢楼主。
作者: wmjob    时间: 2009-02-21 20:00
thanks
作者: lenky0401    时间: 2009-02-21 22:10
谢谢大家的支持 最近被老板催得紧 忙着赶毕业论文呢 可怜的小娃。
不过关于lighttpd的文档我仍一直在整理 完成了马上发上来。
作者: 16hotcom    时间: 2009-02-21 23:17
不错,学习之!:wink:
作者: aobai    时间: 2009-02-28 12:42
原帖由 converse 于 2009-2-13 23:05 发表
支持。
结合项目阅读代码是提高编程能力的捷径之一。



准备开始看,现阶段对http协议也不是很熟悉,不知道从server.c开始看能够看懂不。


bless~
作者: neu_linux    时间: 2009-02-28 16:06
根本不能下载!别被骗了
作者: lankai1224    时间: 2009-03-01 09:32
可以下载
作者: lvg    时间: 2009-03-01 18:34
up
作者: zghover    时间: 2009-03-02 09:26
谢谢,学习了!
作者: lenky0401    时间: 2009-03-02 23:50
//by lenky
利用select多路复用I/O的Web服务应用模型

/* 可读、可写、异常三种文件描述符集的申明和初始化。*/
fd_set readfds, writefds, exceptionfds;
FD_ZERO(&readfds);
FD_ZERO(&writefds);
FD_ZERO(&exceptionfds);

int max_fd;

/* socket配置和监听。*/
sock = socket(...);
bind(sock, ...);
listen(sock, ...);

/* 对socket描述符上发生关心的事件进行注册。*/
FD_SET(&readfds, sock);
max_fd = sock;

while(1) {
        int i;
        fd_set r,w,e;
       
        /* 为了重复使用readfds 、writefds、exceptionfds,将它们拷贝到临时变量内。*/
        memcpy(&r, &readfds, sizeof(fd_set));
        memcpy(&w, &writefds, sizeof(fd_set));
        memcpy(&e, &exceptionfds, sizeof(fd_set));
       
        /* 利用临时变量调用select()阻塞等待,等待时间为永远等待直到发生事件。*/
        select(max_fd + 1, &r, &w, &e, NULL);

        /* 测试是否有客户端发起连接请求,如果有则接受并把新建的描述符加入监控。*/
        if(FD_ISSET(&r, sock)){
                new_sock = accept(sock, ...);
                FD_SET(&readfds, new_sock);
                FD_SET(&writefds, new_sock);
                max_fd = MAX(max_fd, new_sock);
        }
        /* 对其它描述符发生的事件进行适当处理。描述符依次递增,最大值各系统有所不同(比如在作者系统上最大为1024),在linux可以用命令ulimit -a查看(用ulimit命令也对该值进行修改)。在freebsd下,用sysctl -a | grep kern.maxfilesperproc来查询和修改。*/
        for(i= sock+1; i<max_fd+1; ++i) {
                if(FD_ISSET(&r, i))
                        doReadAction(i);
                if(FD_ISSET(&w, i))
                        doWriteAction(i);
        }
}


利用poll多路复用I/O的Web服务应用模型
/* 新建并初始化文件描述符集。*/
struct pollfd fds[MAX_NUM_FDS];
int max_fd;

/* socket配置和监听。*/
sock = socket(...);
bind(sock, ...);
listen(sock, ...);

/* 对socket描述符上发生关心的事件进行注册。*/
fds[0].fd = sock;
fds[0].events = POLLIN;
max_fd = 1;

while(1) {
        int i;
       
        /*调用poll()阻塞等待,等待时间为永远等待直到发生事件。*/
        poll(fds, max_fd, -1);

        /* 测试是否有客户端发起连接请求,如果有则接受并把新建的描述符加入监控。*/
        if(fds[0].revents & POLLIN){
                new_sock = accept(sock, ...);
                fds[max_fd].fd = new_sock;
                fds[max_fd].events = POLLIN | POLLOUT;
                ++ max_fd;
        }
        /* 对其它描述符发生的事件进行适当处理。*/
        for(i=1; i<max_fd+1; ++i) {
                if(fds.revents & POLLIN)
                        doReadAction(i);
                if(fds.revents & POLLOUT)
                        doWriteAction(i);
        }
}

利用epoll多路复用I/O的Web服务应用模型
/* 新建并初始化文件描述符集。*/
struct epoll_event ev;
struct epoll_event events[MAX_EVENTS];

/* 创建epoll句柄。*/
int epfd = epoll_create(MAX_EVENTS);

/* socket配置和监听。*/
sock = socket(...);
bind(sock, ...);
listen(sock, ...);

/* 对socket描述符上发生关心的事件进行注册。*/
ev.events = EPOLLIN;
ev.data.fd = sock;
epoll_ctl(epfd, EPOLL_CTL_ADD, sock, &ev);

while(1) {
        int i;
        /*调用epoll_wait()阻塞等待,等待时间为永远等待直到发生事件。*/
        int n = epoll_wait(epfd, events, MAX_EVENTS, -1);
        for(i=0; i<n; ++i) {
                /* 测试是否有客户端发起连接请求,如果有则接受并把新建的描述符加入监控。*/
                if(events.data.fd == sock) {
                        if(events.events & POLLIN){
                                new_sock = accept(sock, ...);
                                ev.events = EPOLLIN | POLLOUT;
                                ev.data.fd = new_sock;
                                epoll_ctl(epfd, EPOLL_CTL_ADD, new_sock, &ev);
                        }
                }else{
                        /* 对其它描述符发生的事件进行适当处理。*/
                        if(events.events & POLLIN)
                                doReadAction(i);
                        if(events.events & POLLOUT)
                                doWriteAction(i);
                }
        }
}

利用kqueue多路复用I/O的Web服务应用模型
/* 新建并初始化文件描述符集。*/
struct kevent changelist[MAX_EVENTS];   
struct kevent eventlist[MAX_EVENTS];
int count = 0;

/* 创建kqueue句柄。*/
int kqfd = kqueue();

/* socket配置和监听。*/
sock = socket(...);
bind(sock, ...);
listen(sock, ...);

/* 对socket描述符上发生关心的事件进行注册。*/
EV_SET(&changelist[0], sock, EVFILT_READ, EV_ADD | EV_ENABLE | EV_CLEAR,
        0, 0, 0);
++ count;

while(1) {
        int i;
        /*调用kevent()阻塞等待,等待时间为永远等待直到发生事件。*/
        int n = kevent(kqfd, changelist, count, eventlist, count, NULL);
        for(i=0; i<n; ++i) {
                /* 测试是否有客户端发起连接请求,如果有则接受并把新建的描述符加入监控。*/
                if(eventlist.ident == sock) {
                        new_sock = accept(sock, ...);
                        EV_SET(&changelist[count], new_sock, EVFILT_READ,
                                EV_ADD | EV_ENABLE | EV_CLEAR, 0, 0, 0);
                        ++ count;
                }else{
                        /* 对其它描述符发生的事件进行适当处理。*/
                        doReadAction(i);
                }
        }
}

利用/dev/poll多路复用I/O的Web服务应用模型
/* 新建并初始化文件描述符集。*/
struct pollfd pfd;
struct pollfd pollfds[MAX_EVENTS];
struct dvpoll dopoll;
int count = 0;

/* 打开/dev/poll设备,创建poll句柄。*/
int dpfd = open("/dev/poll", O_RDWR);

/* socket配置和监听。*/
sock = socket(...);
bind(sock, ...);
listen(sock, ...);

/* 对socket描述符上发生关心的事件进行注册。*/
pfd.fd = sock;
pfd.events = EPOLLIN;
pfd.revents = 0;
write(dpfd, pfd, sizeof(pfd));
++ count;

while(1) {
        int i;
        /*调用ioctl()阻塞等待,等待时间为永远等待直到发生事件。*/
        dopoll.dp_timeout = -1;
        dopoll.dp_nfds = count;
        dopoll.dp_fds = &pollfds;
        int n = ioctl(dpfd, DP_POLL, &dopoll);
        for(i=0; i<n; ++i) {
                /* 测试是否有客户端发起连接请求,如果有则接受并把新建的描述符加入监控。*/
                if(pollfds.fd == sock) {
                        if(pollfds.revents & POLLIN){
                                new_sock = accept(sock, ...);
                                pfd.fd = new_sock;
                                pfd.events = EPOLLIN | POLLOUT;
                                pfd.revents = 0;
                                write(dpfd, pfd, sizeof(pfd));
                                ++ count;
                        }
                }else{
                        /* 对其它描述符发生的事件进行适当处理。*/
                        if(pollfds.revents & POLLIN)
                                doReadAction(i);
                        if(pollfds.revents & POLLOUT)
                                doWriteAction(i);
                }
        }
}

利用rtsig多路复用I/O的Web服务应用模型
/* 新建并初始化关注信号。*/
sigset_t sigset;
siginfo_t siginfo;

sigemptyset(&sigset);
sigaddset(&sigset, SIGRTMIN + 1);
sigaddset(&sigset, SIGIO);


/* socket配置和监听。*/
sock = socket(...);
bind(sock, ...);
listen(sock, ...);

/* 重新设置描述符可读写时发送的信号值。*/
fcntl(sock, F_SETSIG, SIGRTMIN + 1);

/* 对socket描述符设置所有者。*/
fcntl(sock, F_SETOWN, getpid());

/* 启用描述符的信号驱动I/O模式。*/
fcntl(sock, F_SETFL, O_ASYNC | O_NONBLOCK | O_RDWR);

while(1) {
        struct timespec ts;
        ts.tv_sec =  1;
        ts.tv_nsec = 0;
       
        /*调用sigtimedwait()阻塞等待,等待时间1秒。*/
        sigtimedwait(&sigset, &siginfo, &ts);
       
        /* 测试是否有客户端发起连接请求,如果有则接受并把新建的描述符加入监控。*/
        if(siginfo.si_fd == sock) {
                new_sock = accept(sock, ...);
                fcntl(new_sock , F_SETSIG, SIGRTMIN + 1);
                fcntl(new_sock , F_SETOWN, getpid());
                fcntl(new_sock , F_SETFL, O_ASYNC | O_NONBLOCK | O_RDWR);
        }else {
        /* 对其它描述符发生的事件进行适当处理。*/
                doReadAction(i);
        }
}
作者: lenky0401    时间: 2009-03-02 23:52
.................

[ 本帖最后由 lenky0401 于 2009-3-3 10:21 编辑 ]
作者: myfreeke    时间: 2009-03-03 11:37
感谢楼主共享啊,学习一下
作者: ideawu    时间: 2009-03-04 09:42
建议置顶.
作者: aobai    时间: 2009-03-06 14:01
原帖由 lenky0401 于 2009-2-17 09:31 发表



我在看配置信息解析加载的时候 自己实际修改 编译 调试过
你是说 需要把如何修改 编译 调式 写个总结么?

那个和所有linux下程序编译是一样的



在Ubuntu上面安装出现了很多问题,看来入门不容易
作者: lenky0401    时间: 2009-03-06 14:09
原帖由 aobai 于 2009-3-6 14:01 发表



在Ubuntu上面安装出现了很多问题,看来入门不容易


Ubuntu下

$ sudo apt-get install libpcre3-dev
$ sudo apt-get install zlib1g-dev
$ sudo apt-get install libglib2.0-dev

$ sudo apt-get install libaio-dev
$ sudo apt-get install libbz2-dev

$ ./configure
$ make
$ make install


具体可以参考
http://redmine.lighttpd.net/proj ... utorialInstallation
作者: feirxue    时间: 2009-03-08 16:42
标题: 回复 #1 lenky0401 的帖子
研究中.....
作者: zywangyan    时间: 2009-03-08 17:47
谢谢楼主,向楼主学习
作者: fly6    时间: 2009-03-09 10:32
支持,
作者: aobai    时间: 2009-03-09 14:03
原帖由 lenky0401 于 2009-3-6 14:09 发表


Ubuntu下

$ sudo apt-get install libpcre3-dev
$ sudo apt-get install zlib1g-dev
$ sudo apt-get install libglib2.0-dev

$ sudo apt-get install libaio-dev
$ sudo apt-get install libbz2-d ...




除了一些模块需要的其它软件包,在Ubuntu上面直接一个命令就可以安装lighttpd吧,
aptitude install lighttpd lighttpd-doc
而不需要
./configure  这些步骤
作者: lenky0401    时间: 2009-03-09 17:59
To 楼上
当然可以 呵呵
我的意思是如果是自己学习源码的话 还是自己一步步编译啦 这样可以自己修改代码 查看效果
作者: dreamice    时间: 2009-03-09 19:52
支持,好东西
作者: onlyflyer    时间: 2009-03-13 10:05
标题: 回复 #1 lenky0401 的帖子
提个小小的建议:
楼主应该对lighttpd最核心的部分进行一个总体说明,然后再分析代码细节。lighttpd的效率比apache要不少,为什么会高,好在哪里,我觉得搂主可以先概括总结一下。
lightppd的流水线工作模型,利用AIO来提高其吞吐量,这些才是重点的重点,估计也是大家感兴趣的地方。

期待楼主的后续作品。
作者: lenky0401    时间: 2009-03-13 12:05
标题: 回复 #45 onlyflyer 的帖子
非常感谢你的建议 后续的文档已经写了一部分 但是未发出来 因为感觉还不完整 等整理好了 一起发上来
作者: wrr83-chinaunix    时间: 2009-03-13 23:12
怎么下不了呢
作者: hitraistlin    时间: 2009-03-16 22:57
多谢,先顶再细看。
作者: 东海之心    时间: 2009-03-17 13:23
能不能把加了注释的代码share出来呢?呵呵
作者: cu_dark    时间: 2009-03-17 17:39
感谢,先收藏了。
作者: aple_smx    时间: 2009-03-31 17:39
提示: 作者被禁止或删除 内容自动屏蔽
作者: derek    时间: 2009-04-12 20:36
多谢楼主
作者: lenky0401    时间: 2009-04-12 22:08
惭愧 惭愧 总结的这些基础知识 既然把深度潜水级会员引出来了 哈哈
作者: banggou    时间: 2009-04-13 10:44
这个要顶下 呵呵 慢慢看下
作者: ricesty    时间: 2009-04-13 22:34
多谢分享
作者: msingle    时间: 2009-04-14 19:19
提示: 作者被禁止或删除 内容自动屏蔽
作者: lenky0401    时间: 2009-04-14 21:38
标题: 回复 #56 msingle 的帖子
:wink:

[ 本帖最后由 lenky0401 于 2009-4-15 08:02 编辑 ]
作者: 2202877    时间: 2009-04-15 09:37
标题: 回复 #1 lenky0401 的帖子
好,!!谢谢
作者: 惠繪洋    时间: 2009-04-24 12:10
Thanks. This few year I try to use lighttpd to instead of apache..
作者: nicsky    时间: 2009-04-27 13:52
多谢lz
作者: oshell    时间: 2009-04-27 18:06
标题: 回复 #1 lenky0401 的帖子
不错不错!!我顶!!!
作者: 李某人    时间: 2009-04-28 17:01
我下了,留着慢慢琢磨琢磨
作者: qq563403351    时间: 2009-04-29 21:05
顶一下 学习了
作者: bullity    时间: 2009-05-17 21:34
谢楼主
作者: dreamice    时间: 2009-05-18 09:10
有时间准备研究一个web服务器,apache太庞大了,这个倒是不错。感谢分享。
作者: lenky0401    时间: 2009-05-20 00:31
对于Lighttpd中CGI执行流程的多余文字不用过多说明,图片里已经基本说的很清楚了。

从图中,我们可以看到对于客户端的每一个请求(动态页面,也就是需要CGI处理的),Lighttpd进程都是先fork一个CGI进程,然后将请求头(通过环境参数)和请求体(通过管道)传递给CGI程序,等待CGI处理并将从CGI进程那接收到的处理结果再响应给客户端,然后将CGI终止(通过发送SIGTERM信号)。

CGI的处理有一些缺点,先不说其它的,单从图中可以看到的就有:首先,对于客户端的每一个请求都需要fork一个CGI进程,然后在该请求处理结束后又将该CGI进程kill掉,性能自然是不高的。其次,Web Server(这里指Lighttpd)和CGI之间通信采用无名管道(PIPE)进行通信,因此具有无名管道的所有缺点(比如:Web Server进程和CGI必须具有亲缘关系;管道是半双工的,数据只能向一个方向流动,因此为了使Web Server和CGI进行双方通信,必须建立起两个管道等等)。最两个缺点就衍生出很多其它的缺点,比如基本无法进行分布式部署和在CGI侧进行负载均衡等。

所以Lighttpd里除了提供CGI外,还有另外两个选择SCGI和FASTCGI,将陆续会有Lighttpd里的SCGI,FASTCGI等模块的分析内容发出,感兴趣的网友可以关注,

转载保留本博客地址连接[http://lenky0401.cublog.cn/]。

CGI的相关信息可以查看地址:http://www.w3.org/CGI/



[ 本帖最后由 lenky0401 于 2009-5-20 18:57 编辑 ]
作者: aobai    时间: 2009-05-20 13:25
想问下这个图是怎么画的,用都什么工具?
作者: jenson87    时间: 2009-05-27 21:43
标题: 好东西
谢谢分享你所学的,继续,支持中
作者: bullity    时间: 2009-05-28 13:26
楼主加油
等你的FASTCGI模块分析
作者: Roemer    时间: 2009-05-28 15:21
up
作者: dandy    时间: 2009-05-29 01:01
文件都损坏了???
作者: lenky0401    时间: 2009-05-29 14:08
标题: 回复 #71 dandy 的帖子
不至于吧?呵呵,需要的话PM我,我通过邮件发给你就是。
作者: anders0913    时间: 2009-06-18 12:09
认真的看了一遍文档,相当的好,顶楼主~~
作者: cake918    时间: 2009-07-09 21:52
thank you ,这可省了我不少的时间!
作者: xieweihua    时间: 2009-07-13 11:48
楼主断续,
真不错。

希望能有更多的更新出来。
作者: elfofocean    时间: 2009-07-14 14:27
多谢多谢,看看先
作者: gaosboy    时间: 2009-08-20 11:22
好东西!!!必须顶,偷走看看
作者: jolonchan    时间: 2009-08-23 20:02
受教了!确实不错
作者: wanghr    时间: 2009-09-21 17:29
太有用啦!谢谢楼主分享!
作者: guojianlee    时间: 2009-09-22 11:15
mark 一下
作者: andy851899    时间: 2009-11-29 16:21
楼主很强,最近正在读lightppd-1.4.25源码,对我来说帮助应该很大,谢谢
作者: zhanglistar    时间: 2010-01-04 09:57
标题: 回复 #1 lenky0401 的帖子
在阅读lighttpd到makefile过程中,有几处不太懂

1.am__tar = ${AMTAR} chof - "$$tardir"
am__untar = ${AMTAR} xf -

$$tardir这个是什么用法?后面有几处tardir的赋值语句
dist-gzip: distdir
    tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
    $(am__remove_distdir)
其他类似   

整个makefile中没有看到tardir的定义了  , 请问$$tardir是什么用法呢?
在其他地方也看到好多$$var的用法的,

$(AMTAR)是tar命令

2.am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
该语句中有几个地方不懂,
makefile中也可以这样连续赋值?
CDPATH和
ZSH_VERSION+.  都没有看到定义   这句话表示什么意思呢?

3.NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
作者写了这几个变量,但是没有看到引用,只定义了 ,为什么要这么作?

4.install-am: all-am
    @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
$(AM_MAKEFLAGS)    是个变量 但是没有看到定义 ,难道在makefile之外定义的?     不解
$(MAKE) 应该是个变量  但是 makefile中有这么一行     
.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \
    install-strip
这个是什么用法呢?  
只看见过.PHONY    难道是自己定义到隐含规则?


小弟刚入门学makefile  希望各位能够指点一下   
3ks in advance
作者: zhyclt    时间: 2010-01-04 10:22
恩 ,很不错的东西哦
作者: wachmc    时间: 2010-01-13 00:08
标题: 回复 #1 lenky0401 的帖子
学习, 等基础好了认真学习下
作者: sky-鹏    时间: 2010-04-12 10:28
谢谢楼主·~~
作者: Dead_Dance    时间: 2010-04-27 16:49
不错~ 学习了
作者: lenky0401    时间: 2010-04-29 14:04
被挖了
作者: cqm    时间: 2010-06-01 10:06
好东西,收下了慢慢研读
作者: riccy    时间: 2010-06-01 18:46
收藏了,的确是好东西
作者: jpai2289    时间: 2010-07-15 16:17
好贴,肯定要支持的。。。
作者: anders0913    时间: 2010-07-15 16:28
每次看都有收获啊{:3_193:}
作者: jssfy    时间: 2010-07-15 17:21
回复 1# lenky0401


    LZ好厉害
作者: chris_zley    时间: 2010-07-21 10:21
伸展树那个真看不懂,旋转的原则是什么?
作者: jz1043    时间: 2010-09-01 21:34
这么好的东西必须顶。。。。。。。。。。
作者: youyou1986925    时间: 2010-09-02 21:07
MARK
作者: lscc9    时间: 2010-09-02 21:41
MARK, 收藏了
作者: jz1043    时间: 2010-09-04 21:57
楼主要是能把那本书共享给大家就好了。。。
作者: gnubuntu    时间: 2010-09-09 08:48
提示: 作者被禁止或删除 内容自动屏蔽
作者: zffl    时间: 2010-10-10 11:51
最近也打算开始分析lighttpd源码,参考学习。。:em03:
作者: lnitcscq    时间: 2010-10-31 12:31
不错,lz觉得这个开源的软件哪里让你觉得最好




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2