Linux面试高频(Linux基础)
Linux基础
1 常见Linux指令⭐⭐⭐
Linux是一个开源的操作系统,其命令行界面(CLI)是用户与系统交互的主要方式。以下是一些常见的Linux指令及其介绍:
- cd:切换当前目录或工作目录。例如,cd /home/user表示进入/home/user目录。
- ls:列出当前目录或文件的列表。
- cp:复制一个或多个文件到指定的位置或将指定的内容写入目标位置的文件中。
- mv:移动或重命名一个或多个文件。
- rm:删除一个或多个文件。
- mkdir:创建一个新的目录。
- rmdir:删除一个空目录。
- pwd:显示当前工作目录的路径。
- ping:测试网络连接是否正常。
- top:显示系统的运行情况,包括进程和系统资源的使用情况。
- tar:打包、解包和压缩文件。
- grep:在文件中查找匹配的文本。
- find:在指定的目录下查找文件。
- chmod:修改文件或目录的权限。
- chown:更改文件或目录的所有者。
以上仅是Linux系统中的一部分常用命令,还有许多其他的命令可以用来管理文件系统、网络连接、进程等。学习Linux命令需要一定的时间和实践,但掌握它们可以大大提高工作效率。
2 常见GCC指令⭐⭐⭐
在Linux中,GCC(GNU Compiler Collection)是一个开源的编译器集合,包括了C、C++、Objective-C、Fortran等语言的编译器。以下是一些常用的GCC编译器命令和编译流程:
- 安装GCC:在大多数Linux发行版中,GCC已经预装了。如果没有预装,可以通过包管理器或从官方网站下载并安装。
- 编译一个C程序:使用gcc编译器可以编译C程序。例如,要编译一个名为“hello.c”的C程序,可以使用以下命令:
gcc hello.c -o hello
这将生成一个名为“hello”的可执行文件。
- 编译一个C++程序:使用g++编译器可以编译C++程序。例如,要编译一个名为“hello.cpp”的C++程序,可以使用以下命令:
g++ hello.cpp -o hello
这将生成一个名为“hello”的可执行文件。
- 编译一个Objective-C程序:使用g++编译器可以编译Objective-C程序。例如,要编译一个名为“hello.m”的Objective-C程序,可以使用以下命令:
g++ -fobjc-arc -framework Foundation hello.m -o hello
这将生成一个名为“hello”的可执行文件。
- 编译一个Fortran程序:使用gfortran编译器可以编译Fortran程序。例如,要编译一个名为“hello.f90”的Fortran程序,可以使用以下命令:
gfortran hello.f90 -o hello
这将生成一个名为“hello”的可执行文件。
- 编译一个Makefile项目:Makefile是一种用于自动化构建项目的脚本语言。要编译一个Makefile项目,需要先编写一个Makefile文件,然后使用make命令进行编译。例如,要编译一个名为“myproject”的项目,可以使用以下命令:
make
这将自动编译所有的源文件并生成可执行文件。
以上是一些常用的GCC编译器命令和编译流程,但还有很多其他命令和选项可以使用。在使用GCC时,应该仔细阅读文档以了解所有可用的选项和参数。
3 常见GDB调试指令⭐⭐⭐
GDB(GNU Debugger)是一个开源的调试器,它可以用来调试C、C++和Fortran等编程语言程序。以下是一些常见的GDB调试指令及其介绍:
- break point:在指定位置设置断点,使程序停止在此处。例如,break file.c:50表示在file.c文件的第50行设置一个断点。
- continue:跳过当前正在执行的代码,继续执行下一条指令。例如,continue命令可以在程序中跳过一段代码并继续执行后续代码。
- step into:进入函数内部,查看函数的参数和局部变量的值。例如,step into命令可以进入名为my_function的函数内部。
- step over:跳过函数调用和表达式,只查看函数或表达式的值。例如,step over命令可以跳过my_function函数调用和表达式。
- print:打印变量的值。例如,print variable可以打印变量的值。
- info registers:显示当前寄存器的值。例如,info registers可以显示当前寄存器的值。
- list:列出当前源代码文件的所有行号。例如,list命令可以列出当前源代码文件的所有行号。
- next:逐行执行程序,直到遇到下一个断点。例如,next命令可以逐行执行程序,直到遇到下一个断点。
- finish:结束调试会话。例如,finish命令可以结束调试会话
以上仅是GDB中的一部分常用指令,还有许多其他的指令可以用来查看内存状态、单步执行程序、修改变量值等。学习GDB指令需要一定的时间和实践,但掌握它们可以大大提高程序员的调试效率。
4 常见Linux驱动开发指令⭐⭐⭐⭐
在Linux中,可以使用Shell脚本来加载和卸载驱动程序。以下是一些常用的指令:
- 加载驱动程序:使用modprobe命令可以加载模块文件并将其注册到内核中。例如,要加载名为"driver.ko"的驱动程序,可以使用以下命令:
sudo modprobe driver.ko
- 卸载驱动程序:使用rm命令可以删除已经加载的模块文件。例如,要删除名为"driver.ko"的驱动程序,可以使用以下命令:
sudo rm driver.ko
需要注意的是,加载和卸载驱动程序需要具有足够的权限才能执行。通常情况下,只有root用户或者拥有相关权限的用户才能够执行这些指令。同时,为了避免误删或覆盖其他重要的文件,建议在使用这些指令时谨慎操作。
5 常见Linux文件操作命令⭐⭐⭐
以下是一些常见的Linux文件操作命令:
- ls:列出当前目录下的文件和子目录。
- cd:切换到指定的目录。
- pwd:显示当前工作目录的路径。
- mkdir:创建一个新的目录。
- rmdir:删除一个空目录。
- cp:复制文件或目录。
- mv:移动或重命名文件或目录。
- rm:删除文件或目录。
- touch:创建一个新文件或更新现有文件的时间戳。
- cat:将文件内容输出到终端。
- less:逐页查看文件内容。
- head:显示文件的前几行。
- tail:显示文件的后几行。
- grep:在文件中查找匹配的字符串。
- find:在指定目录及其子目录中查找文件。
- chmod:更改文件或目录的权限。
17.chown:更改文件或目录的所有者。
这些命令只是Linux文件操作的一部分,还有很多其他命令可以用于不同的文件操作任务。
6 Linux权限管理命令⭐⭐⭐
Linux权限管理是Linux系统中非常重要的一部分,它用于控制用户和组对文件、目录和其他资源的访问权限。在Linux中,每个文件和目录都有一个所有者(owner)、一个所属组(group)和一个其他人(others)三部分组成,其中所有者和所属组决定了文件或目录的访问权限,而其他人则决定了其他用户对该文件或目录的访问权限。
以下是一些常用的Linux权限管理命令:
- chmod:更改文件或目录的权限。可以使用数字模式来指定权限,例如755表示所有者有读写执行权限,所属组有读写执行权限,其他人只有读权限。
- chown:更改文件或目录的所有者。
- chgrp:更改文件或目录的所属组。
- su:切换用户身份。
- sudo:以超级用户身份运行命令。
- pwd:显示当前工作目录的路径。
- whoami:显示当前登录用户的用户名。
- groups:列出当前用户所属的所有组。
- id:显示当前用户的UID和GID。
- usermod:修改用户的属性。
- groupmod:修改用户的组属性。
- adduser:创建新用户。
- deluser:删除用户。
- passwd:修改用户的密码。
- userdel:删除用户。
这些命令只是Linux权限管理的一部分,还有很多其他命令可以用于不同的权限管理任务。
7 Linux磁盘管理及命令⭐⭐⭐⭐
Linux磁盘管理是Linux系统中非常重要的一部分,它用于管理硬盘、分区和文件系统等。在Linux中,可以使用命令行工具来管理磁盘和文件系统,以下是一些常用的Linux磁盘管理命令:
- fdisk:创建、删除、格式化和挂载分区表。
- mkfs:创建、删除、格式化和挂载文件系统。
- lsblk:列出所有可用的块设备。
- blkid:显示每个块设备的UUID。
- mount:将文件系统挂载到指定目录。
- umount:卸载已挂载的文件系统。
- fsck:检查和修复文件系统错误。
- resize2fs:调整文件系统的块大小。
- btrfs-monitor:监视和报告Btrfs文件系统的健康状况。
- ddrescue:备份和恢复损坏的分区。
这些命令只是Linux磁盘管理的一部分,还有很多其他命令可以用于不同的磁盘管理任务。
8 linux下检查内存状态的命令⭐⭐⭐⭐
- free命令:用于查看系统内存的使用情况,包括总内存、已用内存、可用内存等。示例命令:free -h
- top命令:除了显示系统的整体资源使用情况外,还可以查看每个进程的内存使用情况。示例命令:top
- vmstat命令:显示系统的虚拟内存统计信息,包括内存使用情况、交换空间使用情况等。示例命令:vmstat
- /proc/meminfo文件:该文件提供了系统内存的详细信息,可以使用cat或者less命令来查看。示例命令:cat /proc/meminfo
- pmap命令:用于显示进程内存映射的详细信息,包括内存地址、权限、映射的文件等。示例命令:pmap <进程ID>
9 什么是Uboot?⭐⭐⭐⭐⭐
Bootloader(引导加载程序)是一种在操作系统启动前运行的小型程序,负责初始化硬件并加载操作系统内核到内存中。它通常存储在设备的固件(如BIOS或UEFI)中,是系统启动的关键步骤。
Uboot启动过程中做了哪些事:
1、汇编阶段
- 切换到svc模式;
- 为了保证启动稳定,关闭看门狗、中断、MMU、cache;
- 初始化硬件,要做的操作有初始化时钟,串口,内存等硬件;
- 时钟很多硬件都要用到,所以先初始化;
- uboot搬到内存中;
- 准备好C语言要使用的栈空间;
2、C代码阶段
- 大部分硬件的初始化;
- 把内核搬到内存运行,搬到内存运行会快很多。
- 加载内核;
10 文件系统⭐⭐⭐
根文件系统(Root File System)是操作系统启动时挂载的第一个文件系统,是整个文件系统层次结构的基础,在操作系统运行中起着至关重要的作用。以下从多个方面详细介绍根文件系统:
定义与基本概念
根文件系统是 Linux 或其他类 Unix 系统中文件系统的根目录(/
)所对应的文件系统。它包含了操作系统启动、运行以及用户操作所需的基本文件和目录结构。当操作系统启动时,内核会首先挂载根文件系统,然后在此基础上进行后续的初始化操作和其他文件系统的挂载。
组成结构
根文件系统通常包含以下重要的目录和文件:
/bin
:存放用户级的基本命令,如ls
、cp
、mv
等,这些命令在系统启动过程中以及普通用户登录后都可以使用。/sbin
:存放系统级的管理命令,如shutdown
、reboot
、ifconfig
等,通常只有超级用户(root)才能执行这些命令。/etc
:包含系统和应用程序的配置文件,如网络配置文件、用户账户信息文件等。例如,/etc/passwd
文件存储了用户账户的基本信息。/lib
:存放系统和应用程序运行所需的共享库文件,这些库文件提供了程序运行时所需的函数和代码。/dev
:设备文件目录,包含了所有硬件设备的抽象表示,如硬盘、串口、鼠标等。通过操作这些设备文件,用户和程序可以与硬件设备进行交互。/mnt
:挂载点目录,用于临时挂载其他文件系统,如外部存储设备(U 盘、移动硬盘)等。/root
:超级用户(root)的主目录。/home
:普通用户的主目录,每个用户在/home
目录下都有一个以自己用户名命名的子目录。
作用与功能
- 系统启动支持:根文件系统包含了内核启动所需的必要文件,如初始化脚本、设备驱动等。内核在挂载根文件系统后,会执行其中的初始化脚本,完成系统的初始化工作,如加载设备驱动、启动系统服务等。
- 提供基本命令和工具:根文件系统中的
/bin
和/sbin
目录提供了系统和用户操作所需的基本命令和工具,使得用户可以进行文件管理、进程管理、网络配置等操作。 - 存储系统配置信息:
/etc
目录中的配置文件记录了系统的各种配置信息,如网络设置、用户账户信息、服务启动配置等。这些配置文件决定了系统的运行方式和行为。 - 设备管理:
/dev
目录中的设备文件允许用户和程序通过文件操作的方式访问和控制硬件设备,实现了硬件设备的抽象和统一管理。
类型与格式
根文件系统可以采用不同的文件系统类型,常见的有:
- ext2/ext3/ext4:是 Linux 系统中常用的文件系统类型,具有较高的性能和可靠性,支持文件系统日志功能(ext3 和 ext4),可以提高文件系统的恢复能力。
- JFFS2:适用于嵌入式系统,具有较好的闪存支持能力,能够有效处理闪存的擦写限制和坏块管理。
- YAFFS2:也是一种常用于嵌入式系统的文件系统,专门为 NAND 闪存设计,具有高效的空间利用和快速的读写性能。
构建与部署
构建根文件系统通常需要使用工具链和相关的脚本,将所需的文件和目录结构打包成一个文件系统镜像。常见的构建工具包括 BusyBox、Buildroot 等。部署根文件系统时,可以将生成的镜像烧录到存储设备(如硬盘、SD 卡)上,或者通过网络进行挂载(如 NFS 挂载)。
11 文件系统的常用目录⭐⭐⭐
Linux文件系统中一般有如下几个目录:
/bin目录
- 该目录下存放所有用户都可以使用的、基本的命令,这些命令在挂接其它文件系统之前就可以使用,所以/bin目录必须和根文件系统在同一个分区中。
- /bin目录下常用的命令有:cat,chgrp,chmod,cp,ls,sh,kill,mount,umount,mkdir,mknod,test等,我们在利用Busybox制作根文件系统时,在生成的bin目录下,可以看到一些可执行的文件,也就是可用的一些命令。
/sbin 目录
- 该目录下存放系统命令,即只有管理员能够使用的命令,系统命令还可以存放在/usr/sbin,/usr/local/sbin目录下,/sbin目录中存放的是基本的系统命令,它们用于启动系统,修复系统等,与/bin目录相似,在挂接其他文件系统之前就可以使用/sbin,所以/sbin目录必须和根文件系统在同一个分区中。
- /sbin目录下常用的命令有:shutdown,reboot,fdisk,fsck等,本地用户自己安装的系统命令放在/usr/local/sbin目录下。
/dev目录
- 该目录下存放的是设备文件,设备文件是Linux中特有的文件类型,在Linux系统下,以文件的方式访问各种设备,即通过读写某个设备文件操作某个具体硬件。比如通过"dev/ttySAC0"文件可以操作串口0,通过"/dev/mtdblock1"可以访问MTD设备的第2个分区。
/etc目录
- 该目录下存放着各种配置文件,对于PC上的Linux系统,/etc目录下的文件和目录非常多,这些目录文件是可选的,它们依赖于系统中所拥有的应用程序,依赖于这些程序是否需要配置文件。在嵌入式系统中,这些内容可以大为精减。
/lib目录
- 该目录下存放共享库和可加载(驱动程序),共享库用于启动系统。运行根文件系统中的可执行程序,比如:/bin /sbin 目录下的程序。
/home目录
- 用户目录,它是可选的,对于每个普通用户,在/home目录下都有一个以用户名命名的子目录,里面存放用户相关的配置文件。
/root目录
- 根用户的目录,与此对应,普通用户的目录是/home下的某个子目录。
/usr目录
- /usr目录的内容可以存在另一个分区中,在系统启动后再挂接到根文件系统中的/usr目录下。里面存放的是共享、只读的程序和数据,这表明/usr目录下的内容可以在多个主机间共享,这些主要也符合FHS标准的。/usr中的文件应该是只读的,其他主机相关的,可变的文件应该保存在其他目录下,比如/var。/usr目录在嵌入式中可以精减。
/var目录
- 与/usr目录相反,/var目录中存放可变的数据,比如spool目录(mail,news),log文件,临时文件。
/proc目录
- 这是一个空目录,常作为proc文件系统的挂接点,proc文件系统是个虚拟的文件系统,它没有实际的存储设备,里面的目录,文件都是由内核临时生成的,用来表示系统的运行状态,也可以操作其中的文件控制系统。
/mnt目录
- 用于临时挂载某个文件系统的挂接点,通常是空目录,也可以在里面创建一引起空的子目录,比如/mnt/cdram /mnt/hda1 。用来临时挂载光盘、硬盘。
/tmp目录
- 用于存放临时文件,通常是空目录,一些需要生成临时文件的程序用到的/tmp目录下,所以/tmp目录必须存在并可以访问。
12 中断⭐⭐⭐⭐⭐
硬中断、软中断是什么?有什么区别
硬中断
由与系统相连的外设(比如网卡、硬盘)自动产生的,主要是用来通知操作系统系统外设状态的变化。
- 可屏蔽中断 ——当 CPU 接收到更高优先级的中断时,这些中断可以被延迟。
- 不可屏蔽中断 ——无法延迟这些中断。 CPU 应该立即考虑它们。
软中断
为了满足实时系统的要求,中断处理应该是越快越好。linux为了实现这个特点,当中断发生的时候,硬中断处理那些短时间就可以完成的工作,而将那些处理事件比较长的工作,放到中断之后来完成,也就是软中断(softirq)来完成。
区别
- 引发对象:硬中断是由外设引发的,软中断是执行中断指令产生的,无需外部施加中断请求信号。
- 提供中断号:硬中断的中断号是由中断控制器提供的,软中断的中断号由指令直接指出,无需使用中断控制器。
- 耗时:硬中断处理程序要确保它能快速地完成任务,这样程序执行时才不会等待较长时间,称为上半部。软中断处理硬中断未完成的工作,是一种推后执行的机制,属于下半部。
硬中断(Hardware Interrupts)是由外部设备发起的,通常用于表示设备需要CPU的注意,例如I/O操作完成、定时器中断等。硬中断通常是可屏蔽的,这意味着在处理某个硬中断过程中,CPU可以禁止响应其他硬中断,以防止嵌套中断带来的问题。当然,也有一些特定情况下的硬中断是不可屏蔽的,例如非屏蔽中断(Non-Maskable Interrupt, NMI)。
软中断(Software Interrupts)则是由软件主动触发的,通常用于实现系统调用、异常处理等。软中断的可屏蔽性取决于具体实现和系统需求。在某些情况下,软中断可能是不可屏蔽的,以确保某些关键任务或异常处理能够得到优先执行。然而,在其他情况下,软中断可能是可以屏蔽的,以避免嵌套中断或提高系统性能。
13 中断上半部和下半部理解⭐⭐⭐⭐⭐
在嵌入式系统或操作系统中,中断处理通常分为上半部(Top Half)和下半部(Bottom Half),目的是在快速响应中断的同时,高效处理复杂任务。以下是两者的核心区别和协同工作机制:
1. 中断上半部
- 定义:中断服务程序(ISR)的紧急部分,运行在中断上下文(Interrupt Context)中,必须快速执行。
- 特点:紧急任务:处理与硬件直接相关的紧急操作(如清除中断标志、保存寄存器状态、读取硬件数据)。不可阻塞:不能使用可能导致睡眠的函数(如等待队列、动态内存分配)。可被抢占:允许更高优先级的中断打断当前中断处理,确保实时性。时间敏感:执行时间必须极短(通常在微秒级),避免阻塞其他中断。
2. 中断下半部
- 定义:非紧急任务的延迟处理部分,运行在进程上下文(Process Context)或内核线程中。
- 特点:非紧急任务:处理数据处理、状态更新、通知应用等耗时操作(如网络协议解析、传感器数据处理)。可阻塞:允许使用睡眠函数或复杂逻辑(如工作队列)。不可被抢占:通常由内核调度,不会被其他中断打断(取决于实现机制)。时间宽松:执行时间较长(毫秒级),但需保证整体系统性能。
3. 上下半部的协同机制
- 上半部触发下半部:上半部完成紧急操作后,通过标记事件或调度任务触发下半部执行。例如:网络接收中断中,上半部读取数据并放入缓冲区,然后触发下半部解析协议。定时器中断中,上半部更新时间,下半部处理超时任务。
- 下半部实现方式:软中断(Softirq):内核预定义的低优先级中断,用于高频任务(如网络、调度)。Tasklet:基于软中断的轻量级任务,同一类型的 tasklet 只能串行执行。工作队列(Workqueue):内核线程,可处理需要睡眠的复杂任务。
4. 关键区别
对比 |
上半部 |
下半部 |
运行上下文 |
中断上下文 |
进程上下文(或内核线程) |
紧急程度 |
必须立即处理 |
可延迟处理 |
阻塞能力 |
不可阻塞 |
可阻塞(如使用工作队列) |
执行时间 |
极短(微秒级) |
较长(毫秒级) |
可抢占性 |
允许更高优先级中断抢占 |
不可被中断抢占 |
5. 应用场景
- 上半部示例:清除硬件中断标志、读取 ADC 数据、应答外设请求。
- 下半部示例:处理 ADC 数据滤波、更新用户界面、发送网络数据包。
总结
上下半部的设计平衡了实时性和处理效率:
- 上半部快速响应中断,确保系统及时处理紧急事件;
- 下半部异步处理复杂任务,避免阻塞中断响应。通过这种机制,系统能高效应对高频硬件事件,同时保证整体稳定性。
14 ioctl和unlock_ioctl有什么区别?⭐⭐⭐
ioctl和unlock_ioctl是Linux内核中的两个函数。
- ioctl: 这是一个系统调用接口,用于在用户空间和内核空间之间进行通信。它允许用户程序通过设备文件发送命令和参数给设备驱动程序,并执行相应的操作。设备驱动程序可以根据收到的命令来执行不同的操作。
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
该专栏面向嵌入式开发工程师、C++开发工程师,包括C语言、C++,操作系统,ARM架构、RTOS、Linux基础、Linux驱动、Linux系统移植、计算机网络、数据结构与算法、数电基础、模电基础、5篇面试题目、HR面试常见问题汇总和嵌入式面试简历模板等文章。超全的嵌入式软件工程师面试题目和高频知识点总结! 另外,专栏分为两个部分,大家可以各取所好,为了有更好的阅读体验,后面会持续更新!!!