2012年03月 存档

Boa源码分析 – 3 – 三个函数简析

2012年03月25日,星期日

下面看一下boa.c里面的三个函数:create_server_socket, drop_privs和 drop_privs。这三个函数都被声明为static表示,静态函数对普通函数的区别就是他只能在当前文件中可见。

static int create_server_socket(void)
{
    int server_s;
    server_s = socket(SERVER_AF, SOCK_STREAM, IPPROTO_TCP);
    //创建套接字SERVER_AF在compat.h中声明被声明为INET或INET6
    if (server_s == -1) {
        DIE("unable to create socket");
    }
    //DIE在defines.h中的宏定义为
    //#define DIE(mesg) log_error_mesg(__FILE__, __LINE__, mesg), exit(1)
    //__FILE__和__LINE__分别表示当前文件和当前行
    //log_error_mesg在log.c中有定义,向标准输出输出错误信息

    /* server socket is nonblocking */
    if (set_nonblock_fd(server_s) == -1) {
        DIE("fcntl: unable to set server socket to nonblocking");
    }//把套接字设定成非阻塞的,set_nonblock_fd在defines.h中为宏替代real_set_nonblock_fd(在util.c中定义)

    /* close server socket on exec so cgi's can't write to it */
    if (fcntl(server_s, F_SETFD, 1) == -1) {
        DIE("can't set close-on-exec on server socket!");
    }//将文件描述符标记设定为1,当执行exec族函数时关闭套接字

(更多…)

Boa源码分析 – 2 – boa.c流程

2012年03月24日,星期六

下面来看看boa.c吧

/* set umask to u+rw, u-x, go-rwx */
    c = umask(~0600);
    if (c == -1) {
        perror("umask");
        exit(1);
    }
    devnullfd = open("/dev/null", 0);
    /* make STDIN and STDOUT point to /dev/null */
    if (devnullfd == -1) {
        DIE("can't open /dev/null");
    }
    if (dup2(devnullfd, STDIN_FILENO) == -1) {
        DIE("can't dup2 /dev/null to STDIN_FILENO");
    }
    if (dup2(devnullfd, STDOUT_FILENO) == -1) {
        DIE("can't dup2 /dev/null to STDOUT_FILENO");
    }

这里设定了权限掩码为~600,也就是生成文件权限为rw——-,然后打开/dev/null,它相当于一个黑洞,输入任何东西都会丢失,读取也什么都读取不到,因为服务器进程是在守护进程,所以将标准输入输出定向到/dev/null。下面看getopt:
(更多…)

Boa源码分析 – 1 – Makefile

2012年03月20日,星期二

boa是一个小型的webserver,设计目标是速度和安全,虽然这个项目已经很多年没有更新了,但是对于初学linux编程,网络编程的同学来说。。还是很有价值的。boa的实际代码量只有7000+(去掉autotools自动生成的东西),初看压力不大。当然还有一些适合学习的开源项目,如thttpd(也是一个http server,代码12000+行),redis(key-value存储系统,和Memcached类似,里面貌似有好多数据结构?两万多行)和coreutils (常用linux命令源码,什么cd,chmod,cp等等),还有好多,github和sourceforge上有很丰富资源。。

直接入题吧,boa也用到了Autotools,但是我实在是搞不清楚autotools的几个命令是怎么组织的。。干脆直接./configure ,开始分析Makefile。
(更多…)

make 知识小记

2012年03月19日,星期一

/*写完来吐槽下,,make的语法够多够复杂的。。。*/

make 可以简化编译过程,如果有一个近百个源文件的项目,如果有个文件更改后工程需要重新编译,那么一直用gcc -c a.c这些个命令敲来敲去会屎人的。运行make时候,他会寻找指定目录下(默认是 .)的Makefile文件并且分析依赖关系进行必要的编译。

Makefile文件的基本格式很简单:

目标文件: 依赖文件1 依赖文件2 依赖文件3 。。。。

[tab]编译命令

他的意思是目标文件是依赖于冒号后面几个文件的,如果这些依赖文件有更新的,那么其目标文件也需要更新。
(更多…)

grep 用法简述

2012年03月16日,星期五

grep( global search regular expression(RE) and print out the line)是一个在文本中搜索模式并且把有匹配文本的行输出出来的工具,使用的前提是要知道一下正则表达式相关的知识。grep命令的基本格式如下

grep -选项 ‘搜索字符串’ 文件

当我们不加‘文件’参数的时候,grep默认从标准输入读入。每处理一行,如果能搜索到匹配模式的,就将整行输出出来。如果有很多文件,那么搜索到一行,将会在行前面加上文件名前缀。比如搜索当前文件夹下所有文件下有那些行包含‘fcntl‘ ,那么就用 grep ’fcntl‘ *。

不同的选项有不同的效果:

-c 输出匹配的行的数目
-i 忽略搜索串中的字母大小写
-n 输出行号
-v 反向选择,输出不满足要求的行
-a 在二进制文件中查找
-r 递归搜索子文件夹中的文件
-E 使用扩展正则表达式进行匹配, egrep 相当于 grep -E
-Hh h显示文件名前缀,H不显示。默认显示。
-A n 显示匹配行之后n行(After)
-B n 显示匹配行开始到之前n行(Before)
-C n 相当于-A n -B n = =||
-d recurse|read|skip recurse表示递归处理子目录(-d recurse先当于 -r),skip表示忽略,read表示把目录做成一般文件

grep包含的工具还有egre (更多…)

GCC编译流程与常用选项

2012年03月14日,星期三

学了很长时间的c和c++,对于gcc的用法还不是很清楚,只会用“gcc a.c -o a”这类的命令。至于预处理,编译,汇编,链接等过程不是十分清楚。前两天到图书馆借了本快速入门的书,学习了下,现在做个小小的总结。

编译的基本流程:

c(.c)和c++(.cc, .cpp, .cxx)的源文件 。

|| gcc -E a.c -o a.i // 如果不加-o参数,gcc会把处理过的源文件放到标准输出中

预处理后的源文件。c源文件预处理后后缀为.i, c++为.ii 。

|| gcc -S a.i //会在当前文件夹下生成a.s

编译后生成的汇编源代码。后缀为.s, .S 。

|| gcc -c a.s //只进行汇编生成目标文件,.o结尾的目标文件可以用(ar crv libabc.a a.o b.o c.o )打包成形如lib×××.a的静态库

目标文件与库文件进行链接,生成可执行文件。

||gcc  a.o //在当前文件夹下生成a.out

基本的过程就是以上四步。其中任何一种状态,用gcc如果不加-c,-E,-S选项都会直接生成可执行文件,如果加上了选项,可以由之前任一状态生成所需要的文件(如gcc -S a.c 可以直接生成a.s,gcc -c a.i可以直接生成a.o )。如果是c++直接换用g++命令就行。

另外gcc -v可以输出编译过程的配置和版本信息。

gcc警告提示: (更多…)

一个简单的vector实现

2012年03月13日,星期二

学算法用的是《数据结构与算法分析(c++描述)》,里面有用c++实现算法和数据结构的,我看了看感觉不错,就把敲了出来。
ps:不是我写的,,基本是照抄的,不过倒是学到不少东西。

vector的特点就是可以动态的改变数组的大小,一般的vector应该是容量不够的时候扩展到2倍的容量,微软的实现应该是不够的时候扩展到1.5倍容量.
(更多…)

一个简单的list实现

2012年03月9日,星期五

此List仿照的时STL中的list 写的,完成了一些基本功能。学习时候时按照书上(数据结构与算法分析,c++描述)学习的,了解到了迭代器的基本实现,感觉很有成就感。List用双向链表实现的,这样就可以方便地对迭代器应用++,–操作符。链表中又添加了两个节点tail和head,这样在插入删除元素的时候在操作上就统一了。

虽然说写出来了,而且经过简单的测试,没有啥问题(当然,我没有做任何的错误处理。。),但是感觉这种接口与实现分离的写法实在是太麻烦了。以后考虑把这些接口都放到注释中去,然后再在实际代码中实现,这样就不用去写一堆的template<typename Object>了。

前两天学习了git的用法,准备把自己的代码放到github上面,repo名称为fkcode。有兴趣的可以watch me。放代码~

#include<iostream>
template<typename Object>
class List{
private:
	struct Node;	//存放节点信息
	int theSize;	//List包含的元素的个数
	Node *head,*tail; //当容器为空的时候,有两个节点

	void init();
public:
	class const_iterator; //const迭带器
	class iterator;			//迭带器

	List();//constructor
	List( const List & rhs );
	~List();
	const List & operator= (const List & rhs );
	//the "Big Three"

	//basic routines, easy to understand by name
	iterator begin();
	iterator end();
	const_iterator begin() const;
	const_iterator end() const;

	int size() const;
	bool empty() const;
	void clear();

	Object & front();
	Object & back();
	const Object & front() const;
	const Object & back()  const;

	void push_front( const Object & x );
	void push_back(  const Object & x );
	void pop_front();
	void pop_back();

	iterator insert( iterator itr, const Object & x );
	iterator erase( iterator itr );
	iterator erase( iterator start, iterator end );

};

(更多…)

标准I/O库之缓冲

2012年03月4日,星期日

标准io提供缓冲的目的是尽可能减少read和write的调用。他对每个流进行缓冲管理,减少了编码的复杂度。标准IO库提供了三种类型的缓冲。

1.全缓冲。当缓冲区填满之后才进行实习操作,驻留在磁盘上的文件通常都是全缓冲的。在第一个流上执行第一次io操作时,相关函数用malloc获得所需的缓冲区。

2.行缓冲。在输入和输出中遇到换行符的时候,标准库执行IO操作。当流涉及到一个终端的时候,通常使用行缓冲。

3.不带缓冲。标准IO库不对字符进行缓冲储存,stderr通常时不带缓冲的,这就可以使出错信息可以尽快显示出来。

当且仅当标准输入和标准输出并不涉及互交式设备时候,流才是全缓冲的。

标准出错输出不会是全缓冲的。

可以用setbuf,setvbuf更改流的缓冲类型。

下面有个程序很好的解释了以上:
(更多…)

APUE 文件和目录 几个小知识点

2012年03月3日,星期六

如果用open或creat创建已经存在的文件,则该文件的访问权限位不变。

文件中的空洞是由所设置的偏移量超过文件的尾端,并写了某些数据造成的。空洞不占用磁盘空间,只是打开文件时在内核用一个值为0的数据结构表示。相同长度的文件,含有空洞的文件占用的磁盘块(du  <文件>)可能少一些,用这可以大致判断一个文件是否有空洞。

int unlink( const char *pathname )函数删除目录项,并将由pathname所引用文件的链接技术 -1,如果还有指向该文件的其他链接,则仍然可以通过其他链接访问该文件的数据。只有当链接计数达到0时,该文件的内容才会删除。另一个条件也会阻止删除文件的内容—-只要有进程打开了该文件,其内容也不能删除。如果pathname是符号链接,那么unlink删除符号链接,而不会删除由该链接所引用的文件。给出符号链接的情况下,没有一个函数能删除由该链接所引用的文件。

我们也可以用remove函数删除对一个文件活目录的链接,对于文件,remove的用能与unlink相同,对于目录,remove的功能与rmdir相同。

内核对目录树的深度没有内在限制,但是如果路径名的长度超过了PATH_MAX,则有许多命令会失败。

stat结构中st_atime,st_mtime,st_ctime分别是文件数据的最后访问时间,文件数据的最后修改时间,i节点状态的最后更改时间。

父目录中的每一个子目录都会使该父目录的链接计数增1.