切记预编译和编译与处理是两个不一样的概念(网上不少人都把这两个混为一谈,包括百度百科)node
预编译就是将一些经常使用的、被反复使用的并且几乎不改变的代码进行提早编译放到一个文件中,这样即便程序中其余部分进行了修改,在编译时也不须要对预编译好部分进行从新编译,大大提升了编译时的效率。linux
一般有两种状况须要预编译。面试
第一种状况就是,程序中经常使用的模块,好比某些通用的函数,这些函数会被重复使用,并且代码稳定,几乎不怎么被修改,这时候咱们就能够将这些模块进行预编译并生成函数库。chrome
第二种状况是,对于程序中多个模块都须要包含的头文件,咱们能够将他们放到一块儿,而后进行预编译,也就是“预编译头”技术,VS中的stdafx.h就是处理这种状况的。浏览器
库的概念?服务器
库是写好的现有的,成熟的,能够复用的代码。现实中每一个程序都要依赖不少基础的底层库。
网络
动态库与静态库的概念多线程
先回顾一下编译过程:socket
静态库在连接阶段,会将汇编生成的目标文件.o与引用到的库一块儿连接打包到可执行文件中,对应的连接方式称为静态连接。试想一下,静态库与汇编生成的目标文件(.o文件)一块儿连接为可执行文件,那么静态库一定跟.o文件格式类似。其实一个静态库能够函数
简单当作是一组目标文件(.o/.obj文件)的归档集合,即不少目标文件通过压缩打包后造成的一个文件。静态库特色总结:
一、静态库对函数库的连接是放在编译时期完成的。
二、程序在运行时与函数库再无瓜葛,移植方便。
三、浪费空间和资源,由于全部相关的目标文件与牵涉到的函数库被连接合成一个可执行文件。
除了上面提到的浪费空间和资源的弊端,使用静态库还有另外一个问题:对程序的更新、部署和发布页会带来麻烦。若是静态库libtest.a更新了,全部使用它的应用程序都须要从新编译、发布给用户。
使用动态库正好能够有效解决静态库的这些问题:动态库在程序编译时并不会被链接到目标代码中,而是在程序运行是才被载入。不一样的应用程序若是调用相同的库,那么在内存里只须要有一份该共享库的实例,规避了空间浪费问题。动态库在程序运行是才被载入,也解决了静态库对程序的更新、部署和发布页会带来麻烦。用户只须要更新动态库便可,增量更新。
gcc中静态库使用ar命令,实际上就是打包编译好的.o文件
而动态库使用gcc中的-shared选项。
volatile修饰的变量,告诉编译器在读取该变量值的时候,不要进行优化,而是直接读取变量的值。
应用:
一、 并行设备的硬件寄存器
二、 中断服务子程序中会访问到的非自动变量
三、 多线程应用中被几个任务共享的变量。
进程:进程是程序运行的实例,是系统进行资源分配和调度的一个独立单位,它包含独立的地址空间。
线程:也被叫作轻量级进行,CPU调度的最小单位,使用进程的的地址空间。
进程有本身独立的地址空间,不一样进程之间地址空间是不同的。线程使用其所在进程的地址空间,可是拥有本身的堆栈。一个线程死掉会影响到该线程所在进程的全部线程,可是一个进程死掉却不影响其余进程的运行(360和chrome标签页)
exec是替换进程映像
当进程调用一种exec函数时,源进程彻底由新程序代换,而新程序则从其main函数开始执行。由于调用exec并不建立新进程,因此先后的进程ID并未改变。exec只是用另外一个新程序替换了当前进程的正文、数据、堆和栈段。特别地,在原进程中已经打开的文件描述符,在新进程中仍将保持打开,除非它们的“执行时关闭标志”(close on exec flag)被置位。任何在原进程中已打开的目录流都将在新进程中被关闭。
fork函数是复制进程映像
咱们能够经过调用fork建立一个新进程。这个系统调用复制当前进程,在进程表中新建一个新的表项,新表项中的许多属性与当前进程是相同的。新进程几乎与元进程如出一辙,执行的代码也彻底相同,可是新进程有本身的数据空间、环境和文件描述符。
system是先fork再exec
好比ctrl-c 发送 SIGINT 信号,用于终止正在运行的程序。
ctrl-z 发送 SIGTSTP 信号,经常使用于挂起一个进程。
在程序中能够设计本身的信号处理函数,来进行进程间的通讯。
管道是一个存在于内核空间(内存中)的特殊文件,而且数据只能单向流动,并且只能用于具备亲缘关系的进程间(即父子进程,兄弟进程),无亲缘关系的进程是不能使用的。若是要使用管道进行全双工通讯,那么就要创建两个管道,经过管道通讯的两个进程,一个进程向管道写数据,而另外一个进程从管道读数据。
命名管道是创建在实际的磁盘介质或文件系统(而不是只存在于内存中)上有本身名字的文件,任何进程能够在任什么时候间经过文件名或路径名与该文件创建联系。为了实现命名管道,引入了一种新的文件类型——FIFO文件(遵循先进先出的原则)。实现一个命名管道实际上就是实现一个FIFO文件。命名管道一旦创建,以后它的读、写以及关闭操做都与普通管道彻底相同。虽然FIFO文件的inode节点在磁盘上,可是仅是一个节点而已,文件的数据仍是存在于内存缓冲页面中,和普通管道相同。
顾名思义,共享内存就是容许两个不相关的进程访问同一个逻辑内存。共享内存是在两个正在运行的进程之间共享和传递数据的一种很是有效的方式。不一样进程之间共享的内存一般安排为同一段物理内存。进程能够将同一段共享内存链接到它们本身的地址空间中,全部进程均可以访问共享内存中的地址,就好像它们是由用C语言函数malloc分配的内存同样。而若是某个进程向共享内存写入数据,所作的改动将当即影响到能够访问同一段共享内存的任何其余进程。
linux中
shmget函数用来建立共享内存
互斥体和信号量还有管程
信号量机制的引入解决了进程同步的描述问题,但信号量的大量同步操做分散在各个进程中不便于管理,还有可能致使系统死锁。如:生产者消费者问题中将P、V颠倒可能死锁。
为此Dijkstra于1971年提出:把全部进程对某一种临界资源的同步操做都集中起来,构成一个所谓的秘书进程。凡要访问该临界资源的进程,都需先报告秘书,由秘书来实现诸进程对同一临界资源的互斥使用。
竞争资源和进程间推动顺序非法
(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已得到的资源保持不放。
(3) 不剥夺条件:进程已得到的资源,在末使用完以前,不能强行剥夺。
(4) 循环等待条件:若干进程之间造成一种头尾相接的循环等待资源关系。
main函数的返回值用于说明程序的退出状态。若是返回0,则表明程序正常退出;返回其它数字的含义则由系统决定
从main返回。
调用exit
调用_eixt或者_Exit
最后一个线程从启动例程返回
最后一个线程调用pthread_exit
答案:*((void (*)( ))0x100000 ) ( ); 首先要将0x100000强制转换成函数指针,即: (void (*)())0x100000 而后再调用它: *((void (*)())0x100000)(); 用typedef能够看得更直观些: typedef void(*)() voidFuncPtr; *((voidFuncPtr)0x100000)();
DLL没有本身的栈区,须要依赖于线程的栈,可是有本身的堆,因此在DLL堆中申请的资源最好在DLL中释放。
一个进程建立的多个线程:每一个线程都拥有本身私有的Stack,但共享一个Heap
switch中表达式只能为整型、字符型、枚举型,case语句中的表达式也同样
首先,每一个主机都会在本身的ARP缓冲区中创建一个ARP列表,以表示IP地址和MAC地址之间的对应关系。
2:当源主机要发送数据时,首先检查ARP列表中是否有对应IP地址的目的主机的MAC地址,若是有,则直接发送数据,若是没有,就向本网段的全部主机发送ARP数据包,该数据包包括的内容有:源主机 IP地址,源主机MAC地址,目的主机的IP 地址。
3:当本网络的全部主机收到该ARP数据包时,首先检查数据包中的IP地址是不是本身的IP地址,若是不是,则忽略该数据包,若是是,则首先从数据包中取出源主机的IP和MAC地址写入到ARP列表中,若是已经存在,则覆盖,而后将本身的MAC地址写入ARP响应包中,告诉源主机本身是它想要找的MAC地址。
4:源主机收到ARP响应包后。将目的主机的IP和MAC地址写入ARP列表,并利用此信息发送数据。若是源主机一直没有收到ARP响应数据包,表示ARP查询失败。
广播发送ARP请求,单播发送ARP响应。
客户端浏览器经过DNS解析到www.baidu.com 的IP地址220.181.27.48,经过这个IP地址找到客户端到服务器的路径。客户端浏览器发起一个HTTP会话到220.181.27.48,而后经过TCP进行封装数据包,输入到网络层。
二、在客户端的传输层,把HTTP会话请求分红报文段,添加源和目的端口,如服务器使用80端口监听客户端的请求,客户端由系统随机选择一个端口如5000,与服务器进行交换,服务器把相应的请求返回给客户端的5000端口。而后使用IP层的IP地址查找目的端。
三、客户端的网络层不用关心应用层或者传输层的东西,主要作的是经过查找路由表肯定如何到达服务器,期间可能通过多个路由器,这些都是由路由器来完成的工做,我不做过多的描述,无非就是经过查找路由表决定经过那个路径到达服务器。
四、客户端的链路层,包经过链路层发送到路由器,经过邻居协议查找给定IP地址的MAC地址,而后发送ARP请求查找目的地址,若是获得回应后就可使用ARP的请求应答交换的IP数据包如今就能够传输了,而后发送IP数据包到达服务器的地址。
答:当DNS客户机须要在程序中使用名称时,它会查询DNS服务器来解析该名称。客户机发送的每条查询信息包括三条信息:包括:指定的DNS域名,指定的查询类型,DNS域名的指定类别。基于UDP服务,端口53. 该应用通常不直接为用户使用,而是为其余应用服务,如HTTP,SMTP等在其中须要完成主机名到IP地址的转换。
交换机
在计算机网络系统中,交换机是针对共享工做模式的弱点而推出的。交换机拥有一条高带宽的背部总线和内部交换矩阵。交换机的全部的端口都挂接在这条背 部总线上,当控制电路收到数据包之后,处理端口会查找内存中的地址对照表以肯定目的MAC(网卡的硬件地址)的NIC(网卡)挂接在哪一个端口上,经过内部 交换矩阵迅速将数据包传送到目的端口。目的MAC若不存在,交换机才广播到全部的端口,接收端口回应后交换机会“学习”新的地址,并把它添加入内部地址表 中。
交换机工做于OSI参考模型的第二层,即数据链路层。交换机内部的CPU会在每一个端口成功链接时,经过ARP协议学习它的MAC地址,保存成一张 ARP表。在从此的通信中,发往该MAC地址的数据包将仅送往其对应的端口,而不是全部的端口。所以,交换机可用于划分数据链路层广播,即冲突域;但它不 能划分网络层广播,即广播域。
交换机被普遍应用于二层网络交换,俗称“二层交换机”。
交换机的种类有:二层交换机、三层交换机、四层交换机、七层交换机分别工做在OSI七层模型中的第二层、第三层、第四层盒第七层,并所以而得名。
2)路由器
路由器(Router)是一种计算机网络设备,提供了路由与转送两种重要机制,能够决定数据包历来源端到目的端所通过 的路由路径(host到host之间的传输路径),这个过程称为路由;将路由器输入端的数据包移送至适当的路由器输出端(在路由器内部进行),这称为转 送。路由工做在OSI模型的第三层——即网络层,例如网际协议。
路由器的一个做用是连通不一样的网络,另外一个做用是选择信息传送的线路。 路由器与交换器的差异,路由器是属于OSI第三层的产品,交换器是OSI第二层的产品(这里特指二层交换机)。
3)网关
网关(Gateway),网关顾名思义就是链接两个网络的设备,区别于路由器(因为历史的缘由,许多有关TCP/IP 的文献曾经把网络层使用的路由器(Router)称为网关,在今天不少局域网采用都是路由来接入网络,所以如今一般指的网关就是路由器的IP),常常在家 庭中或者小型企业网络中使用,用于链接局域网和Internet。 网关也常常指把一种协议转成另外一种协议的设备,好比语音网关。
在传统TCP/IP术语中,网络设备只分红两种,一种为网关(gateway),另外一种为主机(host)。网关能在网络间转递数据包,但主机不能 转送数据包。在主机(又称终端系统,end system)中,数据包需通过TCP/IP四层协议处理,可是在网关(又称中介系 统,intermediate system)只须要到达网际层(Internet layer),决定路径以后就能够转送。在当时,网关 (gateway)与路由器(router)尚未区别。
在现代网络术语中,网关(gateway)与路由器(router)的定义不一样。网关(gateway)能在不一样协议间移动数据,而路由器(router)是在不一样网络间移动数据,至关于传统所说的IP网关(IP gateway)。
网关是链接两个网络的设备,对于语音网关来讲,他能够链接PSTN网络和以太网,这就至关于VOIP,把不一样电话中的模拟信号经过网关而转换成数字信号,并且加入协议再去传输。在到了接收端的时候再经过网关还原成模拟的电话信号,最后才能在电话机上听到。
对于以太网中的网关只能转发三层以上数据包,这一点和路由是同样的。而不一样的是网关中并无路由表,他只能按照预先设定的不一样网段来进行转发。网关最重要的一点就是端口映射,子网内用户在外网看来只是外网的IP地址对应着不一样的端口,这样看来就会保护子网内的用户。