C语言面经(操作系统开发zlzx)

C语言

1、static和const的区别

static用于控制作用域。

  1. 修饰全局变量,控制作用域为该文件,其他文件不可访问。
  2. 修饰局部变量,作用域为该函数。在函数内部初始化后不会释放该内存空间,变量的值可以保留。
  3. static变量存储于静态数据区,默认为0。

const是只读的,值不会变化。

  1. 修饰全局变量,存储于常量区,作用域为该文件,其他文件可用过extern访问。
  2. const变量必须在定义时初始化,之后其值不能改变。
  3. const变量可用于修饰函数返回值,返回的内容不能被修改,多用于指针函数中,返回指针时不能改变其指向的内容。

2、函数内部的静态变量保存在哪

静态全局变量和静态局部变量都是静态变量,保存至全局数据区。

内存分区(划分为5个区)
区名内容
栈区存放函数参数和局部变量,编译器自动分配释放,不能返回局部变量的地址
堆区由程序员分配释放,若程序员未释放,程序结束后由操作系统回收。
全局区存放全局变量和静态变量(静态全局和静态局部)
常量区存放常量和字符串
代码区存放函数体的二进制代码,共享且只读,由操作系统进行管理

3、堆区和栈区的区别

  1. 栈区由编译器分配和释放,有静态分配(编译器)和动态分配(malloc函数,仍是编译器分配释放)两种。堆区由程序员手动申请和释放(malloc/new,free/delete),若程序员不释放,在程序结束后会由操作系统释放。
  2. 栈是向低地址扩展的数据结构,是一块连续的内存,先进后出,不会产生碎片。堆是向高地址扩展的内存,内存区域不连续,会产生碎片。
  3. 栈的大小在linux下默认为8M或10M。在多线程任务中,每个线程都需要一个栈,所以其默认值不能太大。
  4. 栈的运行速度更快。但其地址空间需要连续,所以不能过多的使用栈。

4、什么时候要用到编译预处理

编译预处理主要是插入头文件和进行宏定义。
如果某部分变量或代码比较固定,不会经常改变,就可以使用编译预处理。

5、静态链接和动态链接

静态链接是在编译时调用静态库完成的,在生成可执行文件后删除静态库也不会影响其执行。
动态链接是在运行时调用动态库实现的,所以生成的可执行文件中并没有要链接的内容,文件更小,且删除动态库就不能执行。

编译过程
  1. 预处理:插入头文件,进行宏定义。
  2. 编译:进行语法分析,生成汇编文件。
  3. 汇编:将汇编文件转化为二进制目标文件。
  4. 链接:调用静态库(编译时加载)或者动态库(运行时加载)进行链接,生成可执行文件。

6、volatile可以用在什么时候

  1. volatile修饰变量存储于主存中,所有线程可见,属于共享内存。
  2. volatile变量容易被修改,需使用互斥机制访问。
  3. 可用于修饰寄存器变量,因为寄存器会被经常访问。

7、64位编译器中,unsigned long占几个字节

不同编译器下,各变量类型所占内存
类型32位编译器64位编译器
char1个字节1个
short int2个字节2个
指针变量4个字节8个字节
int4个字节4个
unsigned int4个字节4个
float4个字节4个
double8个字节8个
long4个字节8个字节
long long8个字节8个
unsigned long4个字节8个

8、switch语句中不允许的数据类型

  • switch语句中不能为浮点型(float和double)和字符串
  • switch参数和case标签必须为整型常量的表达式。
  • bool类型可用于switch,因为它可以按整数形式转换为1/0。

9、如何通过宏定义获取数组大小

//当时我想到的,不会检查传入参数是否为数组
#define Arraylength(array) (sizeof(array)/sizeof(array[0])
//对方给出的
#define Arraylength(array) 
//c++中提供了ASN检查参数是否为数组
#define Arraylength(array) sizeof(ASN(array))

10、栈和队列的区别

  1. 栈是先进后出,而队列是先进先出。
  2. 栈只能在表的一端进行插入和删除。而队列只能在表的一端进行插入,并在另一端进行删除。

11、二叉树的遍历

先序遍历、中序遍历、后序遍历即为根左右,左根右,左右根。
由先序和中序或者后序和中序皆可确定一棵二叉树。

n个结点可生成多少种二叉树

n的卡特兰数: (2n)! / [(n+1)! * n!] 。

12、在字符串s1中查找s2(串的模式匹配)

若找到,则返回s2在s1中的起始位置,否则返回-1;

int find(char s1[], char s2[])
{
	int i=0, j=0;
	while (s1[i] != '\0' && s2[j] != '\0'){
		if (s1[i] == s2[j]){
			i++;
			j++;
		}
		else{
			i = i-j+1;
			j = 0;
		}
	}
	if (s2[i] == '\0'){
		return i-j+1; //字符串位置从1开始
	}
	else {
		return -1;
	}
}

操作系统(linux)

1、进程线程

  1. 进程是具有一定独立功能的程序在数据集合上的一次动态执行过程。线程是进程中的一条执行流程。
  2. 一个进程可以有多个线程。一个线程崩溃,则其所属进程的其他线程也会崩溃。
  3. 各线程间可以并发执行。共享地址空间和文件等资源。
  4. 进程是资源分配单位,线程是cpu调度单位。
  5. 进程拥有一个完整的资源平台,而线程只独享必不可少的资源,如寄存器和栈。

2、进程状态为Z时,是僵尸态

linux进程的状态(6个)
状态含义
R运行状态(running)进程在运行,或在运行队列中,等待被OS分配时间片(调度)。
S睡眠状态(sleeping)表明进程在等待事件完成,如socket连接,等待信号量唤醒等等,也叫可中断睡眠,可被操作系统杀死。
D磁盘休眠状态(uninterruptible sleeping)即不可中断的状态,进程通常会等待I/O结束。
T停止状态(stopped)表明目前进程正在侦测或停止,可以通过发送SIGSTOP 信号给该进程来停止。被暂停的进程可以通过发送SIGCONT 信号让进程继续运行。
Z僵尸状态(zombies)表明子程序已停止,父程序无法读取子程序结束信息。
X死亡状态(dead)只是一个返回状态,无法捕捉。

Linux进程的六种状态

3、中断需要注意什么

  1. 中断函数不能传参,没有返回值。
  2. 应尽量避免在中断函数中调用数学函数和自定义函数。
  3. 应尽量避免中断程序中进行调度和耗时操作。

4、FIFO调度方式

FIFO是在FCFS调度的基础上加入了优先级来进行任务抢占
调度器从ready队列里获取优先级最高的任务进行调度,除非高优先级任务放弃CPU资源,低优先级的任务永远得不到调度。
优先级相同的任务采用FCFS进行调度。
发生调度的情况:

  • 主动放弃cpu资源(sleep/suspend)
  • 被动放弃cpu资源(mutex/semaphore)
  • 被更高优先级任务抢占

FIFO调度算法

5、互斥

进程同步有两种情况:

  • 间接相互制约关系(资源共享),即互斥地访问临界资源。
  • 直接相互制约关系(相互合作),即多个进程合作去完成一项任务,eg:生产者消费者问题。

临界资源是一次仅允许一个进程访问的资源。产生不可再现性是因为临界资源没有互斥访问。临界区是访问临界资源的代码。
为了防止两个进程同时进入临界区,同步机制应遵循的四条准则:

  1. 空闲让进。资源空闲则让进程获得其使用权
  2. 忙则等待。资源忙则进程等待
  3. 有限等待。进入临界区应保证为有限等待,不会产生死等
  4. 让权等待。不能进入临界区的执行进程应放弃CPU执行权(由于除cpu以外的资源引起等待,此时让出CPU资源)

计算机网络

1、客户服务器的通信过程

一个套接字(socket)就是一个通信标识类型的数据结构,包含了目的地址、端口号和网络传输协议等信息。
套接字通信
客户端和服务器通信

2、三次握手和四次挥手

TCP连接的建立采用客户服务器方式。
三次握手和四次挥手详解

三次握手

三次握手中,本机首先发出建立连接的TCP请求,其首部中的同步位 SYN = 1,序号 seq = 0,表明传送数据时的第一个数据字节的序号是 0;
当目标主机收到建立连接的TCP请求时,接受请求并发回确认。在确认报文段中应使 SYN = 1,使 ACK = 1,其确认号ack = 0+1=1,序号 seq = 0;
本机收到连接接受的报文时,给出确认,其 ACK = 1,确认号 ack = 0+1=1,序号seq= 0+1 = 1。同时,本机的TCP通知上层应用进程,连接已经建立;
目标主机收到本机的确认后,也通知其上层应用进程:TCP连接已经建立。
三次握手

四次挥手

四次挥手中,本机的应用进程先向其 TCP 发出连接释放请求,并停止再发送数据,主动关闭 TCP 连接。连接释放TCP包的首部中,FIN = 1,其序号seq = 596,等待目标主机的确认;
目标主机发出确认,确认号 ack = 596 + 1=597,而这个TCP包的序号 seq = 235。TCP 服务器进程通知高层应用进程。从本机到目标主机的连接已释放,TCP 连接处于半关闭状态。此时目标主机若发送数据,本机仍要接收;
若目标主机已经没有要向本机发送的数据,其应用进程就通知 TCP 释放连接。发出连接释放请求,其 FIN = 1,序号seq = 235,确认号ack = 597,等待对方确认;
本机收到连接释放报文段后,必须发出确认。在确认TCP包中 ACK = 1,确认号 ack =235+ +1=236,自己的序号 seq = 596 + 1=597;
等待2MSL的时间,保证该确认TCP发送至目标主机,然后TCP连接释放完成。

四次挥手

为什么建立连接是三次握手而释放连接需要四次挥手?

因为释放连接时,可能存在数据正在传送的情况。
建立连接的时候,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。 而释放连接时,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,而服务器可能还有数据正在传送给对方,所以服务器可以先发送ACK报文确认释放由客户到服务器的连接,待数据传送完成后,再发送FIN报文释放服务器到客户端的连接。

3、ip地址和物理地址转化使用的协议

ARP地址解析协议:从网络层使用的 IP 地址,解析出在数据链路层使用的硬件MAC地址

4、ping命令使用的协议

ICMP网际控制报文协议:用于IP主机和路由器之间传递控制信息。ping和traceout命令使用的都是ICMP协议。
ping操作主要用于测试另一台主机是否可达,会发送ICMP请求给目标主机,等待其应答。
当我们ping一个网址时,会先通过DNS协议,将ping后接的域名转换为ip地址。(DNS使用的传输层协议是UDP(不可靠))。再通过ARP地址解析服务,由ip地址解析出MAC地址,以便在数据链路层传输。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值