嵌入式基础面-UNIX高编阶段常见面试题整理

本文整理了UNIX/Linux环境下的高级编程面试题目,涵盖文件系统、IO、进程、线程、信号等方面。详细解析了标准I/O与文件I/O的区别、缓存区管理、进程线程的状态转换及同步机制、信号处理、进程通信等内容,是软件开发人员,尤其是嵌入式和系统编程领域的面试必备参考资料。
摘要由CSDN通过智能技术生成

本章详情: 该文章是我在招阶段整理的关于“嵌入式面经”的一些道题目,“软件开发岗位”也可以参考下。涵盖了大多数嵌入式/软件开发岗位常见基础面试题,题目来源是牛客网各大大厂的面经,答案是我逐个查阅资料,理解整理出的答案争取让读者尽可能的容易阅读和理解,部分内容来源于牛客网用户:爱打球的程序员乔丹。资深嵌入式软件开发工程:任立超。

UNIX高编阶段常见习题整理

目录

UNIX高编阶段常见习题整理

一、文件系统与IO

1、 Linux内核空间模型

2、标准I/O和文件I/O有什么区别

3、缓存区的类型和刷新缓存区的方法

4、文件的元信息和文件类型

5、如何得到文件拥有者的名字

6、如何读目录

7、请用3种不同的方法来获取文件长度/大小

二、进程、线程、信号

1、什么是进程,线程?也就是问彼此有什么区别?

2、进程线程的状态转换图,什么时候阻塞,什么时候就绪?

3、父进程、子进程的关系以及区别

4、标准信号和实时信号的区别

6、原子操作

7、进程、多线程的优缺点

8、什么时候用进程,什么时候用线程

9、一个进程可以创建多少线程,和什么有关

10、多进程、多线程同步(通讯)的方法

11、互斥锁与信号量的区别?

12、进程启动和终止的方式!!!

13、main return和exit和_exit进程终止有什么区别

14、什么是守护进程

15、vfork和fork的差别

16、匿名管道的特征

三、网络IPC、socket


一、文件系统与IO

1、 Linux内核空间模型

1)栈区:由编译器自动分配和释放,存放函数的参数值(形

参)、局部变量(int a =1;还有指针变量)等,其操作方式类似于数据结构中的栈,先进后出。

2)堆区:一般由程序员分配和释放,若程序员不释放,可能会造成内存泄漏,程序结束的时候可能由操作系统回收,注意它与数据结构中的堆是两回事,分配方式类似于链表。

3)全局区(静态区):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域(.data),未初始化的全局变量和未初始化的静态变量在相邻的另一块区域(.bss),程序结束后系统释放。

4)文字常量区:常量字符串放在这里,程序结束后有系统释放。

5)程序代码区(.text):存放函数体的二进制代码。

栈的空间有限,堆是很大的自由存储区,程序在编译期对变量和函数分配内存都在栈上进行,且程序运行过程中函数调用时参数的传递也是在栈上进行。

注意:64位操作系统下的虚拟内存空间大小:地址空间大小不是2^32,也不是2^64,而一般是2^48。因为并不需要2^64那么大的寻址空间,过大的空间只会造成资源的浪费。所以64位Linux一般使用48位表示虚拟空间地址,40位标识物理地址。0x0000000000000000~0x00007fffffffffff表示用户空间, 0xFFFF800000000000~ 0xFFFFFFFFFFFFFFFF表示内核空间,共提供256TB(2^48)的寻址空间。

2、标准I/O和文件I/O有什么区别

  • 标准I/O有缓存区 文件I/O没有缓存区

  • 标准I/O是 文件I/O是系统调用

  • 标准I/O可移植性好 文件I/O速度快

  • 标准I/O通过文件流标志打开的文件 文件I/O通过文件描述符标志打开的文件

3、缓存区的类型和刷新缓存区的方法

缓冲区:暂存空间,大多数情况下,缓冲区的存在是件好事,作用合并系统调用

行缓冲:stdout,换行时,满了时,强制刷新 全缓冲:默认,(只要不是终端设备,全采用全缓冲模式)满了时,强制刷新 无缓冲:stderr,需要立即输出

4、文件的元信息和文件类型

(1)元信息

  • 文件的类型和权限

  • 用户ID

  • 组ID

  • 文件字节数

  • 文件块大小

  • 最后一次访问时间

  • 最后一次修改时间

  • 最后一次改变时间(属性)

  • 文件的设备编号

(2)文件类型

  • - 普通文件regular file

  • d 目录文件dirctory

  • b 块设备文件block device

  • c 字符设备文件character device

  • s 套接字文件socket

  • p 管道文件 pipe

  • l 链接文件link

5、如何得到文件拥有者的名字

通过stat()函数得到uid,用getpwuid()读出/etc/passwd每一个字段,并且存放在struct passwd结构体中,结构体中就包括用户名

6、如何读目录

opendir()得到一个目录流,通过目录流读取目录项中的每一个,通过readdir()得到目录项,多次调用时会偏移到每一个元素,当读到最后一个目录流,readdir()返回NULL,之后再closedir()

7、请用3种不同的方法来获取文件长度/大小

  • fseek(fp,0,SEEK_END) ---- num = ftell(fp);

  • lseek(),操作成功返回的是新的文件位置偏移量

  • stat():获取文件的详细信息,然后存储结构体里

  • fgetc() :一个一个字节读

二、进程、线程、信号

1、什么是进程,线程?也就是问彼此有什么区别?

进程:资源(CPU、内存等)分配的基本单位 线程:CPU调度和分配的基本单位

1)当我们运行一个程序的时候,系统就会创建一个进程,并分配地址空间和其他资源,最后把进程加入就绪队列直到分配到CPU时间就可以正式运行了。

2)线程是进程的一个执行流,有一个初学者可能误解的概念,进程就像一个容器一样,包括程序运行的程序段、数据段等信息,但是进程其实是不能用来运行代码的,真正运行代码的是进程里的线程。

3)那么,来看看我们最熟悉的main()函数,我们既可以认为这是一个进程,也可以认为是一个线程。我们都知道,在C/C++中main函数是程序入口,所以准确来说main函数是程序的主线程。然而很神奇的地方在于,当系统在执行main函数的时候,main函数又是一个独立的进程,我们可以在main函数里创建子进程,也可以创建子线程。

4)在main函数里创建的多个子线程中,每个线程有自己的堆栈局部变量,但多个线程也可共享同个进程下的所有共享资源,因此我们经常可以创建多个线程实现并发操作,实现更加复杂的功能。

2、进程线程的状态转换图,什么时候阻塞,什么时候就绪?

创建态(New):一个进程正在被创建,还没到转到就绪状态之前的状态。 就绪态(Ready):一个进程获得了除CPU时间片之外的一切所需资源,一旦得到CPU时间片调度时即可运行。 运行/执行态(Running):当一个进程得到CPU调度正在处理机上运行时的状态。 睡眠/挂起态:由于某些资源暂时不可得到而进入“睡眠态”,将进程挂起,等待唤醒。 阻塞/暂停态(Blocked):一个进程正在等待某一事件而暂停运行时,如等待某资源成为可用,或等待文件读取完成等。 结束/僵尸态(Exit):一个进程正在从系统中消失时的状态,这是因为进程结束或其它因流产所导致。 死亡态:进程生命周期结束了,将所占用的资源还给系统。

我们从父进程调用fork()创建子进程开始讲起,此时子进程处于创建态,此时系统为进程分配地址和资源后将进程加入就绪队列,进入就绪态。就绪态的进程得到CPU时间片调度正式运行,进入执行态。执行态有四种常见结果:

1)当时间片耗光或者被其他进程抢占,则重新进入就绪态,等待下一次CPU时间片;

2)由于某些资源暂时不可得到而进入“睡眠态”(如欲读取的文件为空或者欲获得的某个锁还处于不可获得状态),等待资源可得后再唤醒,唤醒后进入就绪态;

3)收到SIGSTOP/SIGTSTP信号进入暂停态,直到收到SIGCONT信号重新进入就绪态;

4)进程执行结束,通过内核调用do_exit()进入僵尸态,等待系统回收资源。当父进程调用wait()/waitpid()后接收结束子进程,该进程进入死亡态。

3、父进程、子进程的关系以及区别

子进程继承父进程:

○用户号UIDs和用户组号GIDs

○环境Environment

○堆栈

○共享内存

○打开文件的描述符

○执行时关闭(Close-on-exec)标志

○信号(Signal)控制设定

○进程组号

○当前工作目录

○根目录

○文件方式创建屏蔽字

○资源限制

○控制终端

子进程独有的:

○进程号PID

○不同的父进程号

○自己的文件描述符和目录流的拷贝

○子进程不继承父进程的进程正文(text),数据和其他锁定内存(memory locks)

○不继承异步输入和输出

答:子进程从父进程继承的主要有:用户号和用户组号;堆栈;共享内存;目录(当前目录、根目录);打开文件的描述符;但父进程和子进程拥有独立的地址空间和PID参数、不同的父进程号、自己的文件描述符。

4、标准信号和实时信号的区别

信号基本概念:软件模拟中断,进程接受信号后做出相应响应(信号从收到响应依赖于中断,但信号不是中断) 信号会打断阻塞的系统调用,openread等都是阻塞的,会有发生假错(EINTR)的情况

标准信号会丢失,即使发送多个也只会响应一个。 实时信号的响应有固定的顺序,不会丢失,会响应多次。

信号编号(1--31:标准信号,34--64:实时信号)

6、原子操作

原子操作就是: 不可中断的一个或者一系列操作, 也就是不会被线程调度机制打断的操作, 运行期间不会有任何的上下文切换(context switch).

第一步:设置当前进程信号集状态为 目标信号集状态mask,并保存进程旧的信号集状态为 oldmask 第二步:马上进入等待信号阶段 第三步:收到信号唤醒后 设置当前进程信号集状态为 旧的信号集状态oldmask。

7、进程、多线程的优缺点

进程和线程最大的区别和联系,一个进程由PCB(进程控制块)、数据段、代码段组成,进程本身不可以运行程序,而是像一个容器一样,先创建出一个主线程,分配给主线程一定的系统资源,这时候就可以在主线程开始实现各种功能。当我们需要实现更复杂的功能时,可以在主线程里创建多个子线程,跟人多好干活的道理一样,多个线程在同一个进程里,利用这个进程所拥有的系统资源合作完成某些功能。

1)多进程更健壮,一个进程死了不影响其他进程,子进程死了也不会影响到主进程,毕竟系统会给每个进程分配独立的系统资源。多线程比较脆弱,一个线程崩溃很可能影响到整个程序,因为多个线程是在一个进程里一起合作干活的。

2) 进程性能大于线程,每个进程独立地址空间和资源,而多个线程是一起共享了同个进程里的空间和资源,结果就很明显了,线程的性能上限一定比不上进程。

3) 正因为进程性能大于线程。所以这也引发了另一重要知识点,创建多进程的系统花销远大于创建多线程。

4)多进程通讯因为需要跨越进程边界,不适合大量数据的传送,更适合小数据或者密集数据的传送。而多线程无需跨越进程边界,适合各线程间大量数据的传送,甚至还有很重要的一点,多线程可以共享同一进程里的共享内存和变量哦。

5) 多进程逻辑控制比多线程复杂,需要与主进程做好交互。根据上面几点,我们不难知道多进程是“要用来做大事”的,而多线程是“各自做件小事,合作完成大事”。所以要做大事自然就需要更复杂的逻辑控制,不像做小事那么目标明显。

6)虽然多线程逻辑控制比较简单,但是却需要复杂的线程同步加锁控制等机制。

8、什么时候用进程,什么时候用线程

1)创建和销毁较频繁使用线程,因为创建进程花销大嘛。

2)需要大量数据传送使用线程,因为多线程切换速度快,不需要跨越进程边界。

3)并行操作使用线程。线程是为了实现并行操作的一个手段,也就是刚才说的需要多个并行操作“合作完成大事”,当然是使用线程啦。

4)最后可以总结为:安全稳定选进程;快速频繁选线程;

示例:调用外部程序mplayer来播放视频程序框架是,因为播放视频需要的系统资源较大,所以在main函数里先创建一个子进程用来执行播放视频的代码,此时子进程播放视频不影响main函数。最后,main函数执行while(1)死循环一直等待有没有上一部、下一部按键按下,很明显,此时main函数在死循环里无法检验按键按下情况,而检验按键是一件容易且与主线程main函数息息相关的事情,此时就创建子线程来检验按键即可。

最终,子线程检验到“下一部”按键按下,告知主线程main函数,main函数就立刻再次创建子进程再次调用外部程序mplayer播放下一个视频。

9、一个进程可以创建多少线程,和什么有关

一个进程创建线程的个数由虚拟内存分配给线程的调用栈大小决定。 一个线程的栈的大小可以通过ulimit -s指令来查看,一般大多是8M-10M。

10、多进程、多线程同步(通讯)的方法

进程间通讯: (1)管道/无名管道(2)信号(3)共享内存(4)消息队列(5)信号量(6)socket 注意:临界区则是一种概念,指的是访问公共资源的程序片段,并不是一种通信方式。

线程通讯: (1)信号量(2)读写锁(3)条件变量(4)互斥锁(5)自旋锁

11、互斥锁与信号量的区别?

互斥锁用于线程的互斥,信号量用于线程的同步。这是互斥锁和信号量的根本区别,也就是互斥和同步之间的区别。同时互斥锁的作用域仅仅在于线程,信号量可以作用于线程和进程。

12、进程启动和终止的方式!!!

启动:

  • 内核有C启动历程,子进程通过exec用C启动历程替换子进程

  • 启动历程调用main函数使得整个历程启动起来

终止:

5种为正常终止

  • 从main返回;

  • 调用exit:

  • 调用_exit或Exit:

  • 最后一个线程从其启动例程返回:

  • 从最后一个线程调用pthread_exit 。

    异常终止有3种方式,它们是:

  • 调用abort ;

  • 接到一个信号;

  • 最后一个线程对取消请求做出响应。

13、main return和exit和_exit进程终止有什么区别

  • return是返回函数值并退出函数

  • exit结束之前会清理I/O缓存和终止处理程序

  • _exit直接终止程序

14、什么是守护进程

  • pid和ppid和pgid相同

  • 不占用控制终端

15、vfork和fork的差别

(1)fork :子进程拷贝父进程的数据段,代码段

vfork:子进程与父进程共享数据段

(2)fork父子进程的执行次序不确定

vfork保证子进程先运行

16、匿名管道的特征

  • 有空间大小,只能进行单向通信

  • 只适用于有血缘关系之间的进程;

  • 不能用lseek来定位文件偏移量;

  • 在运用管道时把不必要的文件关掉,必须有读写双方

  • 当进程读到一个空管道时会处于阻塞态,直到数据到来。没有写端,返回eof表示读完;

  • 当进程写到一个满管道时会处于阻塞态,直到数据读走。没有读端只有写端,会产生信号结束进程

三、网络IPC、socket

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值