操作系统面试高频(二)线程与进程
1.父进程、子进程的关系以及区别⭐⭐
父子进程的关系:
父进程是创建子进程的进程。当父进程创建一个新的进程时,该新进程就成为子进程。父进程在创建子进程时,会为子进程分配独立的资源和运行环境。
子进程是由父进程创建的新进程。子进程会继承父进程的大部分属性和资源。它可以独立运行,并且可以执行不同的代码路径。子进程可以创建自己的子进程,形成进程的层次结构。
父进程和子进程之间有以下几个区别:
- 进程ID:每个进程在系统中都有一个唯一的进程ID。父进程在创建子进程时,会将子进程的进程ID分配给子进程。
- 进程关系:父进程与子进程之间建立了一种层次关系,父进程是子进程的创造者和管理者。
- 资源继承:子进程会继承父进程的大部分属性和资源,包括打开的文件、环境变量和当前工作目录等。
- 进程通信:父进程和子进程可以通过进程间通信机制来进行交互和数据共享,如管道、共享内存、消息队列等。
- 生命周期:父进程和子进程的生命周期是相互独立的。子进程可以在父进程退出后继续存在,成为孤儿进程,由系统的init进程接管管理。
代码举例:
#include <iostream> #include <unistd.h> #include <sys/types.h> int main() { pid_t pid = fork(); if (pid > 0) { // Parent process std::cout << "Parent process PID: " << getpid() << std::endl; std::cout << "Child process PID: " << pid << std::endl; } else if (pid == 0) { // Child process std::cout << "Child process PID: " << getpid() << std::endl; std::cout << "Parent process PID: " << getppid() << std::endl; } else { // Fork failed std::cerr << "Fork failed" << std::endl; return 1; } return 0; } 这个示例使用了C++的标准库和POSIX(Portable Operating System Interface)的fork函数来创建父子进程。当pid大于0时,表示当前处于父进程,当pid等于0时,表示当前处于子进程。
2.正确处理僵尸进程的方法⭐⭐
1.关于避免产生僵尸进程的方法,在使用fork()创建子进程后,确实应该及时使用wait()或waitpid()系统调用来回收子进程的资源。同时,可以通过注册SIGCHLD信号的处理函数,在函数内部调用wait()或waitpid()来处理子进程的终止状态,以避免僵尸进程的累积。
2.关于使用kill命令来处理僵尸进程,kill命令主要是用来向进程发送信号。如果父进程在子进程退出后没有处理SIGCHLD信号导致出现僵尸进程,可以使用kill命令发送SIGCHLD信号给父进程来触发父进程处理僵尸进程。可以使用以下命令来找到僵尸进程的PID:
ps aux | grep Z
3.然后使用以下命令向父进程发送SIGCHLD信号或强制杀死父进程:
kill -s SIGCHLD <parent_pid>
或者
kill -9 <parent_pid>
这样父进程就会收到SIGCHLD信号或被强制杀死,并由其父进程(通常是init进程)接管处理僵尸进程的清理工作。
3.一个进程可以创建多少线程,和什么有关⭐
理论上,一个进程可用虚拟空间是2G,默认情况下,线程的栈的大小是1MB,所以理论上一个进程可以创建2048个线程,当然更改编译器的设置可以创建多余2048个线程
因此,一个进程可以创建的线程数由可用虚拟空间和线程的栈的大小共同决定,只要虚拟空间足够,那么新线程的建立就会成功。如果需要创建超过2K以上的线程,减小你线程栈的大小就可以实现了,虽然在一般情况下,你不需要那么多的线程。过多的线程将会导致大量的时间浪费在线程切换上,给程序运行效率带来负面影响。
4.什么是进程上下文、中断上下文?⭐⭐⭐
进程上下文(Process Context):
- 进程上下文是指操作系统在执行进程时所需的所有状态信息的集合。
- 包括程序的代码、数据、进程的标识符、堆栈、寄存器的值等。
- 进程上下文的切换通常发生在操作系统的调度器决定切换到另一个进程运行时。
使用场景:
- 当操作系统需要切换正在执行的进程,将CPU资源分配给其他进程时,会发生进程上下文切换。
- 当进程阻塞等待某个事件的发生时,进程上下文可能会被保存,因为此时进程无法继续执行。
中断上下文(Interrupt Context):
- 中断上下文是指当发生中断或异常事件时,硬件或操作系统内核自动保存当前被中断程序的执行现场,并切换到中断处理程序执行的上下文环境。
- 中断上下文包含了被中断程序的寄存器状态、堆栈指针、中断原因等信息。
使用场景:
- 当硬件设备发生某种事件,如I/O完成、定时器中断等,会触发中断,并切换到中断上下文执行中断处理程序。
- 在中断处理程序执行过程中,保存和恢复被中断程序的上下文是必要的,以确保被中断程序的执行能够正确继续。
5.如何创建守护进程⭐⭐⭐⭐⭐
创建守护进程的过程如下:
- 创建子进程:通过在父进程中调用fork()函数来创建子进程。
- 终止父进程:子进程创建后,父进程会调用exit()函数或其他方式终止自身执行,从而使子进程成为孤儿进程。
- 调用setsid()创建新会话:子进程调用setsid()函数创建一个新的会话。这将使子进程成为会话领导者,并且与其父进程和控制终端解除关系。
- 更改当前目录为根目录:守护进程通常将当前工作目录更改为根目录(chdir("/")),这样可以避免后续操作与其他进程的目录关联。
- 重设文件权限掩码:守护进程会调用umask()函数来重设文件权限掩码,这样可以确保守护进程创建的文件具有适当的权限。
- 关闭文件描述符:守护进程会关闭不再需要的文件描述符,比如标准输入、标准输出和标准错误。这可以防止守护进程意外地与控制
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
BG双9,目前在某外企。打算把之前校招时做的笔记通过专栏发出来,本专栏适合于C/C++、嵌入式方向就业的同学,本篇面经总结数千篇面经的知识集合,实时更新全网最新的嵌入式/C++最新内容,囊括了C语言、C++、操作系统、计算机网络、嵌入式、算法与数据结构、数据库等一系列知识点,在我看来这些是求职者在面试中必须掌握的知识点。最后呢祝各位能找到自己合适的工作。