程序中的内存布局

上午看了篇管局内存布局的文章,有点收获,特此理一下思路,总结一番. 程序只用在运行的时候才会加载到内存; 程序没有运行前,虽没有加载到内存,但内存布局可以提前规划,当运行加载内存时,即可用规划好的内存加载。 text(代码区):函数,只读,函数入口地址。 data(数据区):初始化的数据,全局变量、static变量、文字常量区。 bss (未初始化数据):未初始化的全局变量。 heap(堆区):由用户手动申请和释放。 stack(栈区):程序自动申请空间自动释放,非static局部变量。启动后分配。 众所周知,如果只是动态分配空间而不释放,必然导致内存泄露。 1. 栈区普通变量 让指针指向栈区变量,生命周期无需手段管理,其只有作用域的限制。 2.指针指向堆区空间 成功分配内存,则返回堆区首地址; 分配失败,则返回NULL。 需要注意的是malloc()函数越界情况,大小设定0也能编译通过,但必定出错。 free()函数释放的不是变量,释放的是指向的内存,但同一块内存不能连续释放。

Read More

TCP Fast Open 的实现

前两天重装VPS的时候突然发现Shadowsocks支持[TCP Fast Open 特性],找了会资料才理解这个. TCP Fast Open简称TFO,是谷歌为了加速网络传输速度和效率,其特性就是在三次握手的第一次握手时客户端发送(syn+TFO cookie)包;服务端收到后,如果其支持TFO则发出了(ack+syn+TFO cookie)回应包后,立即就开始发数据包,缩短了TTFB的时间;如果服务端不支持TFO,则会发送正常的(syn+ack)回应包,走正常的三次握手流程. 因此,使用TFO的特性需要两端都支持TFO.客户端侧需要Linux Kernel 3.6及以上版本;而服务端侧则是Linux Kernel 3.7及更高版本才支持.并且服务端侧需要设置内核的net.ipv4.tcp_fastopen参数为2或3. net.ipv4.tcp_fastopen参数释义: 1 表示客户端请求开启. 2 表示服务端请求开启. 3 表示客户端与服务端请求同时开启. 服务端使用命令: echo “net.ipv4.tcp_fastopen=3” >> /etc/sysctl.conf sysctl -p 客户端使用命令: echo “net.ipv4.tcp_fastopen=1” >> /etc/sysctl.conf sysctl -p … “TCP Fast Open 的实现”

Read More

Unix环境下C实现网络抓包

拾起去年扔下的UNIX高级环境编程看了下网络编程章节,对着写了点,废话少说. #include <stdio.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netinet/ether.h> #define iip2cip(…) inet_ntoa((struct in_addr){__VA_ARGS__}) #define BUFFER_MAX_SZ 2048 typedef struct mac_frm_hdr { //按照以太网帧格式定义,长度必须一致 unsigned char dest_addr[6]; unsigned char src_addr[6]; unsigned short type; }__attribute__((packed)) MAC_FRM_HDR;//取消编译器自动优化对齐结构体,保证与帧中的结构一致. typedef … “Unix环境下C实现网络抓包”

Read More

C下的__attribute__ 关键字学习

使用__attribute__关键字,首先需要编译器支持,现在绝大多数的编译器都是支持的. 其功能主要是用来在函数或数据声明中设置其属性. __attribute__可以设置函数属性(Function Attribute),变量属性(Variable Attribute)和类型属性(Type Attribute),格式为: _attribute__ ((attribute-list)) 功能有: 1. 错误检查. 函数属性可以帮助开发者把一些特性添加到函数声明中,从而可以使编译器在错误检查方面的功能更强大. 2. 返回声明. __attribute__((noreturn))就是告诉编译器这个函数不会返回给调用者,以便编译器在优化时去掉不必要的函数返回代码. 3. 字节对齐声明.如__attribute__ ((packed))就是高速编译器取消变量或者结构体成员在编译过程中的优化对齐,即按照实际占用字节数进行对齐. 指定字节对齐: struct Test_STU{ char a; int b; short c; }__attribute__(aligned(4)); 指定不对齐: struct Test_STU{ char a; int b; … “C下的__attribute__ 关键字学习”

Read More

C的结构体不定参

在C语言中通常使用内建宏__VA_ARGS__来实现不定参,因此可以也可以使用它实现结构体参数的不定参. 实现如下: #include <stdio.h> #define func(…) func_vars((struct vars_stu){__VA_ARGS__}) struct vars_stu { int x; int y; int z; }; void func_vars(struct vars_stu vs) { printf(“x:%d,y:%d,z:%d\n”, vs.x, vs.y, vs.z); } int main(){ func(1); func(1,2); func(1,2,3); func(.x=1); func(.y=2); … “C的结构体不定参”

Read More

C的string实现

直接使用云风大神的cstring库即可,我写的垃圾可以扔了。 Update:2015/08/23 作为基本常识,C语言中的字符串是利用char数组实现的,并且通常是以\0结尾。但是可惜的是其中并没有保存一个字符串的长度的信息,因此再拷贝或移动时,要么移动整个char数组大小的数据,要么在判断完\0得出长度后再移动数据。这样用起来是极不方便的。因此再C++的STL中就有了string。

Read More

UNIX环境高级编程-进程的运行时环境和运行时资源

Chapter 7-9 [TOC] Runtime Environment 当系统启动时,内核代码被加载到内存,初始化后启动第一个用户进程,然后内核的代码就等着用户进程来调度了。 代码在编译之后会生成一个可执行程序。运行程序其实是用户进程(Shell进程)指示内核要启动另一个用户进程,内核便为这个新的进程分配资源,并加载该进程的代码和数据。 一个程序可以被运行多次,除非发生资源抢占可能会发生启动失败。 Runtime Resources PCB 进程运行时,内核为进程每个进程分配一个PCB(进程控制块),描述进程的详细信息。 PCB在内核中对应的结构体是task_struct。 Virtual Memory 每个进程都会分配虚拟地址空间,在 32 位机下,该地址空间为 4G 。 而在 64 位机下,其虚拟地址只使用了 48 位。所以C程序里,打印的地址都是只有 12 位 16 进制 ,最高为FFFF FFFF FFFF。由于当前 AMD 和 Intel … “UNIX环境高级编程-进程的运行时环境和运行时资源”

Read More

UNIX环境高级编程-File I/O

Chapter 3. File I/O 文件描述符 在Linux系统中,打开的文件是用一个整数来表示的,表示打开文件的整数,称之为文件描述符。当需要往写数据/读数据时,读写函数都需要文件描述符作为参数,以便系统知道用户操作的时哪个文件。 基本操作 open/creat mode选项 解释 O_RDONLY 读方式打开 O_WRONLY 写方式打开 O_RDWR 读写方式打开 O_CREAT 创建文件,如果文件存在,会被截断 O_TRUNC 截断 O_APPEND 追加 O_EXCL 和O_CREAT一起用,如果文件存在则失败 close 关闭文件 read/write 读写文件,会导致文件指针移动。 文件指针和lseek 文件指针是一个整数,描述当前读写位置,可以使用lseek移动文件指针。 文件共享 两个进程可以打开同一个文件进行操作,实现数据的共享。但是当两个文件打开同一个文件进行写操作时,会相互覆盖。当文件被打开两次时,两个文件描述符有各自的文件指针。 内核保存一个全局的文件描述结构体,而一个文件打开两次之后,两个结构体各自有各自的文件指针。 dup/dup2/dup3 dup函数可以复制文件描述符,让两个文件描述符指向同一个文件结构,通过dup复制文件描述符和两次打开文件描述符不同,所以两个文件描述符共享一个文件指针。 … “UNIX环境高级编程-File I/O”

Read More

STL之map和multimap

map的特性: – 所有元素都会根据元素的键值自动排序. – 所有的元素都是pair,同时拥有实值和键值,pair的第一元素被视为键值,第二元素被视为实值,map不允许两个元素有相同的键值. multimap和map的操作类似,唯一区别multimap键值可重复. map和multimap都是以红黑树为底层实现机制. map的使用 //构造 map<T1, T2> mapTT;//map默认构造函数 map(const map &mp);//拷贝构造函数 //赋值 map& operator=(const map &mp);//重载等号操作符 swap(mp);//交换两个集合容器 //大小 size();//返回容器中元素的数目 empty();//判断容器是否为空 max_size();//容器最大数目 //迭代器 begin();//返回set容器迭代器的第一个 end();//返回set容器迭代器的最后一个 rbegin();//返回反向迭代器,以反向开始 rend();//返回反向迭代器到反向结束 cbegin();//同begin(),但属性为const cend();//同end(),但属性为const crbegin();//同rbegin(),但属性为const crend();//同rend(),但属性为const at();//访问元素 … “STL之map和multimap”

Read More

STL之set和multiset

set set的特性: – 所有元素都会根据元素的键值自动被排序。 – set的元素不像map那样可以同时拥有实值和键值,set的元素即是键值又是实值。 – set不允许两个元素有相同的键值。 不可以通过set的迭代器改变set元素的值,因为set元素值就是其键值,关系到set元素的排序规则。如果任意改变set元素值,会严重破坏set组织。换句话说,set的iterator是一种const_iterator. set拥有和list某些相同的性质,当对容器中的元素进行插入操作或者删除操作的时候,操作之前所有的迭代器,在操作完成之后依然有效,被删除的那个元素的迭代器必然是一个例外。 set的使用 //构造 set<T> setT; set(const set &st);//拷贝构造函数 //赋值 set& operator=(const set &st);//重载等号操作符 //迭代器 begin();//返回set容器迭代器的第一个 end();//返回set容器迭代器的最后一个 rbegin();//返回反向迭代器,以反向开始 rend();//返回反向迭代器到反向结束 cbegin();//同begin(),但属性为const cend();//同end(),但属性为const crbegin();//同rbegin(),但属性为const crend();//同rend(),但属性为const //大小 empty();//判断set容器是否为空 max_size();//返回set容器可能包含的元素最大个数 size();//返回当前set容器中的元素个数 … “STL之set和multiset”

Read More