1. C语言中,修饰符volatile含义是什么?其应用场合有哪些?
volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。
2. 请问TCP/IP协议分为哪几层?FTP协议在哪一层?
ISO/OSI的参考模型共有7层,由低层至高层分别为:物理层、数据链路层、网络层、传输层、会话层、表示层、
物理层:在物理媒体上传输原始的数据比特流。
数据链路层:将数据分成一个个数据帧,以数据帧为单位传输。有应有答,遇错重发。
网络层:将数据分成一定长度的分组,将分组穿过通信子网。
传输层:提供不具体网络的高效、经济、透明的端到端数据传输服务。
会话层:进程间的对话也称为会话,会话层管理不同主机上各进程间的对话。
表示层: 为应用层进程提供格式化的表示和转换数据服务。
应用层:提供应用程序访问OSI环境的手段。
应用层:TELNET、FTP、TFTP、SMTP、SNMP、HTTP、BOOTP、DHCP、DNS
表示层:
文本:ASCII,EBCDIC
图形:TIFF,JPEG,GIF,PICT
声音:MIDI,MPEG,QUICKTIME
会话层:NFS、SQL、RPC 、X-WINDOWS、ASP(APPTALK会话协议)、SCP
传输层:TCP、UDP、SPX
网络层:IP、IPX、ICMP、RIP、OSPF(Open Shortest Path First开放式最短路径优先)
数据链路层:SDLC、HDLC、PPP、STP(Spanning Tree Protocol)、帧中继
物理层:EIA/TIA RS-232、EIA/TIA RS-449、V.35、RJ-45
3. 在网络应用中,函数htons,htonl,ntohs,ntohl的作用是什么?
uint32_t htonl(uint32_t hostlong);//32位的主机字节序转换到网络字节序
uint16_t htons(uint16_t hostshort);//16位的主机字节序转换到网络字节序
uint32_t ntohl(uint32_t netlong);//32位的网络字节序转换到主机字节序
uint16_t ntohs(uint16_t netshort);//16位的网络字节序转换到主机字节序
(皆为大小端的改变)
4. C语言中static函数与普通函数的区别是什么?
静态函数
在函数的返回类型前加上关键字static,函数就被定义成为静态函数。
函数的定义和声明默认情况下是extern的,但静态函数只是在声明他的文件当中可见,不能被其他文件所用。
定义静态函数的好处:
<1> 其他文件中可以定义相同名字的函数,不会发生冲突
<2> 静态函数不能被其他文件所用。
局部静态变量
在局部变量之前加上关键字static,局部变量就被定义成为一个局部静态变量。
1)内存中的位置:静态存储区
2)初始化:未经初始化的全局静态变量会被程序自动初始化为0(自动对象的值是任意的,除非他被显示初始化)
3)作用域:作用域仍为局部作用域,当定义它的函数或者语句块结束的时候,作用域随之结束。
全局静态变量
在全局变量之前加上关键字static,全局变量就被定义成为一个全局静态变量。
1)内存中的位置:静态存储区(静态存储区在整个程序运行期间都存在)
2)初始化:未经初始化的全局静态变量会被程序自动初始化为0(自动对象的值是任意的,除非他被显示初始化)
3)作用域:全局静态变量在声明他的文件之外是不可见的。准确地讲从定义之处开始到文件结尾。
好处:
定义全局静态变量的好处:
<1>不会被其他文件所访问,修改
<2>其他文件中可以使用相同名字的变量,不会发生冲突。
5. 请实现内存复制函数void memcpy(void *dst const void *src,int size)
略
1.32位机器上,假设有一个32位数字0x1234abcd保存在0x00000000开始的内存中,那么在little endian和big endian的机器上,按字节该整数在内存中存放的顺序是怎么样的?
little endian:0x00000000-0x000000003h:cd,ab,34,12
big endian: 0x00000000-0x000000003h: 12,34,ab,cd
2.ISO七层模型是什么,tcp/udp属于哪一层?
同上
3.下面是一个中断服务程序的代码,请指出有那些问题?
_interrupt double compute_area(double radius) {
double area= PI*radius*radius;
return area;
}
a、ISR不能返回一个值。
b、ISR不能传递参数。
c、在许多处理器编译器中,浮点一般都是不可冲入的。有些处理器编译器需要让额外的寄存器入栈,有些处理器编译器就不允许在ISR中做浮点运算。此外ISR应该是短而有效率的。在ISR中做浮点运算是不明智的。
4.多任务系统中,常见的任务通讯机制有哪些?
通信方法 无法介于内核态与用户态的原因
管道(不包括命名管道) 局限于父子进程间的通信。
消息队列 在硬、软中断中无法无阻塞地接收数据。
信号量 无法介于内核态和用户态使用。
内存共享 需要信号量辅助,而信号量又无法使用。
套接字 在硬、软中断中无法无阻塞地接收数据。
5.请实现内存复制函数memcpy(void *dst,const void *src,int size).
同上
1、请写出你所知道的C语言关键字。
ANSI C一共只有32个关键字:
auto break case char const continue default do double else enum extern
float for goto if int long register return short signed static sizeof struct
switch typedef union unsigned void volatile while
2、IPv4把所有的IP地址分为A、B、C、D、E五类。请写出B类地址和C类地址的范围和掩码,D类地址的用途是什么?
A类IP地址范围:0.0.0.0到127.255.255.255
B类IP地址范围:128.0.0.0到191.255.255.255
C类IP地址范围:192.0.0.0到223.255.255.255
D类IP地址范围:224.0.0.0到239.255.255.255
E类IP地址范围:224.0.0.0到254.255.255.255
D类地址用于多点播送
E类地址保留,仅作实验和开发用
全零(“0.0.0.0”)地址指任意网络。
全“1”的IP地址(“255.255.255.255”)是当前子网的广播地址。
3、请简述在linux中多进程程序和多线程程序的区别。
对比维度 多进程 多线程 总结
数据共享、同步 数据共享复杂,需要用IPC;数据是分开的,同步简单 因为共享进程数据,数据共享简单,但也是因为这个原因导致同步复杂 各有优势
内存、CPU 占用内存多,切换复杂,CPU利用率低 占用内存少,切换简单,CPU利用率高 线程占优
创建销毁、切换 创建销毁、切换复杂,速度慢 创建销毁、切换简单,速度很快 线程占优
编程、调试 编程简单,调试简单 编程复杂,调试复杂 进程占优
可靠性 进程间不会互相影响 一个线程挂掉将导致整个进程挂掉 进程占优
分布式 适应于多核、多机分布式;如果一台机器不够,扩展到多台机器比较简单 适应于多核分布式 进程占优
4、列出目前linux系统能支持的文件系统,列举常用的四个以上。
yaffs yaffs2 cramfs jffs ramdisk ext2 nfs
5、写一个“标准”宏MIN,这个宏输入两个参数并返回较小的一个?
#define MIN((A),(B)) ((A)<(B)?(A):(B))
6、什么是MMU,MMU的作用?
MMU是Memory Management Unit(内存管理单元)
1)虚拟内存。有了虚拟内存,可以在处理器上运行比实际物理内存大的应用程序。为了使用虚拟内存,操作系统通常要设置一个交换分区(通常是硬盘),通过将不活跃的内存中的数据放入交换分区,操作系统可以腾出其空间来为其它的程序服务。虚拟内存是通过虚拟地址来实现的。
2)内存保护。根据需要对特定的内存区块的访问进行保护,通过这一功能,我们可以将特定的内存块设置成只读、只写或是可同时读写。
7、关键字volatile有什么含义,并给出几个应用场合。
volatile的本意是“易变的” 由于访问寄存器的速度要快过RAM,所以编译器一般都会作减少存取外部RAM的优化,但有可能会读脏数据。当要求使用volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。而且读取的数据立刻被保存。
一般说来,volatile用在如下的几个地方:
1、中断服务程序中修改的供其它程序检测的变量需要加volatile;
2、多任务环境下各任务间共享的标志应该加volatile;
3、存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;
8、双向链表操作题:
*/节点定义*/
typedef srruct node
{
struct node *next;
struct node *previous;
}NODE;
/链表定义/
typedef struct
{
NODE node;
int count;
} LIST;
#define HEAD node.next
#define TALL node.previous
/初始化一个链表/
void lstInit (LIST *pList)
{
pPlist->HEAD=NULL;
pPlist->TALL=NULL;
pPlist->count=0;
}
请编写函数把一个节点(pNode)插入链表pList中某个节点(pPrev)之后。**
略
1.“栈 stack”和“堆 heap”有什么区别,写两个函数分别在栈上和堆上分配内存,在堆上分配内存应注意哪些问题?
1.申请方式
stack:
由系统自动分配。 例如,声明在函数中一个局部变量
int b; 系统自动在栈中为b开辟空间
heap:
需要程序员自己申请,并指明大小,在c中malloc函数
p1 = (char *)malloc(10);
2.申请后系统的响应
栈:
只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。
堆:
首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,
会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表
中删除,并将该结点的空间分配给程序.
3.申请大小的限制
栈:
栈顶的地址和栈的最大容量是系统预先规定好的,是一块连续的内存的区域,在WINDOWS下,栈的大小是2M ,如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。 (有限内存)
堆:
堆是向高地址扩展的数据结构,是不连续的内存区域。(自己分配)
2. 信号量是什么?有什么区别?使用信号量进行任务间通信有何优缺点?
所有进程间通信的方法及优缺点:
1)管道
管道分为有名管道和无名管道
无名管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用.进程的亲缘关系一般指的是父子关系。无明管道一般用于两个不同进程之间的通信。当一个进程创建了一个管道,并调用fork创建自己的一个子进程后,父进程关闭读管道端,子进程关闭写管道端,这样提供了两个进程之间数据流动的一种方式。
有名管道也是一种半双工的通信方式,但是它允许无亲缘关系进程间的通信。
无名管道:优点:简单方便;缺点:1)局限于单向通信2)只能创建在它的进程以及其有亲缘关系的进程之间;3)缓冲区有限;
有名管道:优点:可以实现任意关系的进程间的通信;缺点:1)长期存于系统中,使用不当容易出错;2)缓冲区有限
2)信号量
信号量是一个计数器,可以用来控制多个线程对共享资源的访问.,它不是用于交换大批数据,而用于多线程之间的同步.它常作为一种锁机制,防止某进程在访问资源时其它进程也访问该资源.因此,主要作为进程间以及同一个进程内不同线程之间的同步手段.
优点:可以同步进程;缺点:信号量有限
3)消息队列
消息队列是消息的链表,存放在内核中并由消息队列标识符标识.消息队列克服了信号传递信息少,管道只能承载无格式字节流以及缓冲区大小受限等特点.消息队列是UNIX下不同进程之间可实现共享资源的一种机制,UNIX允许不同进程将格式化的数据流以消息队列形式发送给任意进程.对消息队列具有操作权限的进程都可以使用msget完成对消息队列的操作控制.通过使用消息类型,进程可以按任何顺序读信息,或为消息安排优先级顺序.
优点:可以实现任意进程间的通信,并通过系统调用函数来实现消息发送和接收之间的同步,无需考虑同步问题,方便;缺点:信息的复制需要额外消耗CPU的时间,不适宜于信息量大或操作频繁的场合
4)共享内存
共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问.共享内存是最快的IPC(进程间通信)方式,它是针对其它进程间通信方式运行效率低而专门设计的.它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步与通信.
优点:无须复制,快捷,信息量大;缺点:1)通信是通过将共无法实现享空间缓冲区直接附加到进程的虚拟地址空间中来实现的,因此进程间的读写操作的同步问题;2)利用内存缓冲区直接交换信息,内存的实体存在于计算机中,只能同一个计算机系统中的诸多进程共享,不方便网络通信
3.TCP/IP通信建立的过程怎样,端口有什么作用?
建立:3次握手 断开:4次握手
端口作用:(连接作用)就是让运输层的各种应用进程都能将其数据通过断口向下交付给运输层,以及让运输层知道应当将其报文段的数据向上通过端口交付给应用层相应的进程
4.进程间的通信方法,比较其优缺点
同上
5.什么是MTU,如何检测整个通信链路上的MTU值?
最大传输单元(Maximum Transmission Unit,MTU)
网上说的是在cmd中用ping去查找。。。
6. 请指出下面程序的错误
unsigned char i = 10;
char b = 100;
char* p;
void f(void) {
While(–i>=0)
{ *(p++) = b; }
}
p没有分配空间
i是无符号型,自减操作会引发死循环