为什么栈比堆快

  • 分配和释放:堆在分配和释放时都要调用函数,分配时会到堆空间去寻找足够大小的空间,这些都会花费一定的时间,而栈却不需要这些,栈是程序一开始就分配好的。
  • 访问时间:访问堆的一个具体单元,需要两次,第一次得取得指针,第二次才是真正得到数据,而栈只需访问一次。

线程拥有的资源

在多线程环境下,每个线程拥有一个栈和一个程序计数器。栈和程序计数器用来保存线程的执行历史和线程的执行状态,是线程私有的资源。其他的资源(比如堆、地址空间、全局变量)是由同一个进程内的多个线程共享,在操作共享区域的时候才有可能出现同步需要,操作栈不需要同步。

线程间的通信方式

  • 使用全局变量
  • 使用消息实现通信,Windows中每一个线程都可以拥有自己的消息队列。
  • 使用事件实现线程间通信

线程间的同步方式

各个线程可以访问进程中的公共变量,资源,所以使用多线程的过程中需要注意的问题是如何防止两个或两个以上的线程同时访问同一个数据,以免破坏数据的完整性。

  • 临界区,不是内核对象,所以只能用来同一进程间的线程同步。临界区对应着一个CcriticalSection对象,当线程需要访问保护数据时,调用EnterCriticalSection函数,当对保护数据的操作完成之后,调用LeaveCriticalSection函数释放对临界区对象的拥有权,若未调用,则成为死线程。
  • 互斥量mutex,是内核对象,确保线程拥有对单个资源的互斥访问权。包含一个使用数量、一个线程ID、一个递归计数器。线程ID标示系统中哪个线程当前拥有互斥对象,递归计数器指明线程拥有互斥对象的次数。如果锁定互斥量的线程在终止前未解除锁定,则互斥量会自动释放。
  • 信号量Semaphre,是内核对象,信号量的用法和互斥的用法很相似,不同的是它可以同一时刻允许多个线程访问同一个资源。
  • 事件Event,包含一个使用计数、一个用于指明该事件是个自动重置还是人工重置事件的布尔值。事件能通知一个操作已经完成。

进程间通信方式

  • 信号量( semophore ):信号量是一个计数器,可以用来控制多个进程对共享资源的访问。
  • 消息队列,消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。
  • 信号 ( signal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
  • 共享内存,共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。
  • 套接字( socket ) : 套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同机器间的进程通信。
  • 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。

程序编译过程

  • 预处理,处理宏定义,处理注释,处理#include,保留所有的#pragma编译器指令
  • 编译,把预处理的文件进行词法分析,语法分析,语义分析,优化,最后生成汇编代码
  • 汇编,将汇编代码转为机器可以执行的命令
  • 链接,链接程序运行需要的一大堆目标文件,以及所依赖的其它库文件,最后生成可执行文件。

链接的主要过程包括:地址和空间分配,符号决议,重定位。链接分为静态链接和动态链接。静态链接是指在编译阶段直接把静态库加入到可执行文件中去,这样可执行文件会比较大。而动态链接则是指链接阶段仅仅只加入一些描述信息,而程序执行时再从系统中把相应动态库加载到内存中去。

大端和小端

大端 big-endian 小端 little-endian: 当数据太大,一个字节存不下的时候,我们就得使用多个字节了,即要考虑字节序,是把值的低位存到低地址,还是把值的高位存到低地址。 例如一个16bit的short型x,在内存中的地址为0x0010,x的值为0x1122,那么0x11为高字节,0x22为低字节。对于大端模式,就将0x11放在低地址中,即0x0010中,0x22放在高地址中,即0x0011中。小端模式,刚好相反。常用的X86和ARM结构的计算机都使用小端模式。TCP/IP协议规定使用“大端”字节序为网络字节序。

下面的一段代码可以用来判断计算机是大端的还是小端的,判断的思路是确定一个多字节的值,将其写入内存,然后用指针取其首地址所对应的字节(即低地址的一个字节),判断该字节存放的是高位还是低位,高位说明是Big endian,低位说明是Little endian。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
int main()
{
    unsigned int x = 0x12345678;
    char *c = (char*)&x;
    if (*c == 0x78) {
        printf("Little endian");
    } else {
        printf("Big endian");
    }
}

int类型占多少字节

64位编译器:sizeof(int) = 4, sizeof(float) = 4, sizeof(double) = 8, sizeof(long) = 8,sizeof(int*) = 8 32位编译器:sizeof(int) = 4, sizeof(float) = 4, sizeof(double) = 8, sizeof(long) = 4, sizeof(int*) = 4