
线程和进程的区别是什么本质区别进程是操作系统资源分配的基本单位而线程是任务调度和执行的基本单位在开销方面每个进程都有独立的代码和数据空间程序上下文程序之间的切换会有较大的开销线程可以看做轻量级的进程同一类线程共享代码和数据空间每个线程都有自己独立的运行栈和程序计数器PC线程之间切换的开销小稳定性方面进程中某个线程如果崩溃了可能会导致整个进程都崩溃。而进程中的子进程崩溃并不会影响其他进程。内存分配方面系统在运行的时候会为每个进程分配不同的内存空间而对线程而言除了CPU外系统不会为线程分配内存线程所使用的资源来自其所属进程的资源线程组之间只能共享资源包含关系没有线程的进程可以看做是单线程的如果一个进程内有多个线程则执行过程不是一条线的而是多条线管道有几种方式管道在Linux中有两种方式匿名管道和命名管道。匿名管道是一种在父子进程或者兄弟进程之间进行通信的机制只能用于具有亲缘关系的进程间通信通常通过pipe系统调用创建。命名管道是一种允许无关的进程间进行通信的机制基于文件系统可以在不相关的进程之间进行通信。信号和信号量有什么区别信号一种处理异步事件的方式。信号是比较复杂的通信方式用于通知接收进程有某种事件发生除了用于进程外还可以发送信号给进程本身。信号量进程间通信处理同步互斥的机制。是在多线程环境下使用的一种设施它负责协调各个线程以保证它们能够正确合理的使用公共资源。共享内存怎么实现的共享内存的机制就是拿出一块虚拟地址空间来映射到相同的物理内存中。这样这个进程写入的东西另外一个进程马上就能看到了都不需要拷贝来拷贝去传来传去大大提高了进程间通信的速度。为什么进程崩溃不会对其他进程产生很大影响进程隔离性每个进程都有自己独立的内存空间当一个进程崩溃时其内存空间会被操作系统回收不会影响其他进程的内存空间。这种进程间的隔离性保证了一个进程崩溃不会直接影响其他进程的执行。进程独立性每个进程都是独立运行的它们之间不会共享资源如文件、网络连接等。因此一个进程的崩溃通常不会对其他进程的资源产生影响。进程是分配资源的基本单位那么这个资源指的是什么虚拟内存、文件句柄、信号量等资源。多线程比单线程的优势劣势多线程比单线程的优势提高程序的运行效率可以充分利用多核处理器的资源同时处理多个任务加快程序的执行速度。多线程比单线程的劣势存在多线程数据竞争访问的问题需要通过锁机制来保证线程安全增加了加锁的开销并且还会有死锁的风险。多线程会消耗更多系统资源如CPU和内存因为每个线程都需要占用一定的内存和处理时间。多线程是不是越多越好太多会有什么问题多线程不一定越多越好过多的线程可能会导致一些问题。切换开销线程的创建和切换会消耗系统资源包括内存和CPU。如果创建太多线程会占用大量的系统资源导致系统负载过高某个线程崩溃后可能会导致进程崩溃。死锁的问题过多的线程可能会导致竞争条件和死锁。竞争条件指的是多个线程同时访问和修改共享资源如果没有合适的同步机制可能会导致数据不一致或错误的结果。而死锁则是指多个线程相互等待对方释放资源导致程序无法继续执行。进程切换和线程切换的区别进程切换进程切换涉及到更多的内容包括整个进程的地址空间、全局变量、文件描述符等。因此进程切换的开销通常比线程切换大。线程切换线程切换只涉及到线程的堆栈、寄存器和程序计数器等不涉及进程级别的资源因此线程切换的开销较小。线程切换为什么比进程切换快节省了什么资源为线程共享同一进程的地址空间和资源线程切换时只需切换堆栈和程序计数器等少量信息而不需要切换地址空间避免了进程切换时需要切换内存映射表等大量资源的开销从而节省了时间和系统资源。进程的状态五种状态如何切换进程间通讯有哪些方式管道消息队列共享内存信号信号量socketLinux 进程间通信方式管道Pipe匿名管道内存中特殊文件单向数据流仅父子进程使用生命周期随进程结束。命名管道FIFO文件系统中创建p类型设备文件突破亲缘限制无关系进程可通信遵循FIFO不支持定位。消息队列内核中消息链表支持自定义数据类型消息解决管道无格式问题需用户态/内核态拷贝实时性一般。共享内存直接分配共享空间进程可直接访问无内核态拷贝速度最快需配合信号量解决多进程竞争问题。信号量Semaphore计数器型同步机制P/V原子操作控制资源访问实现互斥与同步保护共享内存等资源。信号Signal异步通信机制内核/硬件/软件可向进程发事件通知进程可默认/捕捉/忽略SIGKILL/SIGSTOP不可捕捉。Socket跨主机/本地进程通信支持TCP可靠、UDP不可靠、本地域套接字是网络通信基础。线程间通信方式互斥锁Mutex作用保护共享资源保证临界区同一时间仅一个线程执行。特点加锁后其他线程阻塞解锁后唤醒竞争开销较大避免死锁需按序获取锁。读写锁R/W Lock作用区分读/写操作读共享、写独占。特点读多写少场景效率高写锁阻塞所有读写读锁允许多线程并发读。条件变量Cond作用实现「等待-通知」同步配合互斥锁使用。特点线程等待条件成立时挂起条件满足后被唤醒解决生产者-消费者等同步问题。自旋锁Spinlock作用用户态轻量锁通过CAS实现原子操作。特点竞争锁时忙等待不主动切换上下文开销小适合锁持有时间极短的场景。信号量Semaphore作用控制资源访问次数支持计数同步。特点P操作减1不足则阻塞、V操作加1唤醒等待者可用于进程/线程间同步。除互斥锁外的常见锁/同步机制读写锁允许多线程同时读仅单线程写读多写少场景提升并发效率。自旋锁加锁失败不阻塞循环忙等临界区极小、锁持有时间极短避免线程切换开销。条件变量配合互斥锁实现等待-通知用于线程需等待某条件成立如生产者-消费者。信号量计数器P/V原子操作可控制并发数、实现同步与互斥。进程调度算法先来先服务 FCFS按到达顺序执行非抢占利于长作业不利于短作业。短作业优先 SJF优先运行预计执行时间最短的进程平均等待时间最短但可能导致长作业饥饿。优先级调度按进程优先级运行可抢占/非抢占优先级高先运行可能产生饥饿。时间片轮转 RR公平分配 CPU 时间片抢占式适合分时系统响应快。多级反馈队列多个优先级队列时间片逐级增大新进程进高优先级用完降级综合性能好Linux 常用。高响应比优先 HRRN响应比 (等待时间服务时间)/服务时间兼顾长短作业避免饥饿。为什么并发执行线程要加锁因为多个线程并发操作共享资源时会产生竞态条件导致数据错乱、结果不可预期。加锁是为了把并行操作变成串行临界区保证同一时刻只有一个线程修改共享数据从而保证数据一致性。死锁四个必要条件互斥资源同一时间只能被一个线程占有持有并等待线程持有资源又申请其他资源且不释放已持有资源不可剥夺资源只能由持有线程主动释放不能被强行抢占环路等待线程之间形成循环等待资源的环如何避免死锁破坏任意一个条件即可。最常用按固定顺序申请锁破坏环路等待。银行家算法作用避免死锁的经典算法在分配资源前先判断系统是否安全。思想像银行放贷一样只在能保证系统安全时才分配资源防止“坏账死锁”。核心步骤计算每个进程还需要的资源检查当前剩余资源能否满足某进程运行若可以让它运行完并释放所有资源重复直到所有进程都能顺利执行得到安全序列关键结论存在安全序列→ 系统安全不会死锁无安全序列 → 可能死锁不分配资源内存管理网络I/O阻塞 IO发起 IO 后一直阻塞直到数据就绪并拷贝完成。简单并发差。非阻塞 IO立即返回需轮询检查是否就绪不阻塞但 CPU 消耗高。IO 多路复用用 select/poll/epoll 同时监听多个 fd哪个就绪处理哪个。高并发服务端常用。信号驱动 IO内核数据就绪时发信号通知再由程序去拷贝。异步通知但拷贝仍阻塞。异步 IO内核完成所有 IO就绪拷贝后再通知进程全程不阻塞。真正异步性能最好。讲一下io多路复用IO多路复用是一种IO得处理方式指的是复用一个线程处理多个socket中的事件。能够资源复用防止创建过多线程导致的上下文切换的开销。select/poll/epoll 内核提供给用户态的多路复用系统调用进程可以通过一个系统调用函数从内核中获取多个事件。select/pollselect 实现多路复用的方式是将已连接的 Socket 都放到一个文件描述符集合然后调用 select 函数将文件描述符集合拷贝到内核里让内核来检查是否有网络事件产生检查的方式很粗暴就是通过遍历文件描述符集合的方式当检查到有事件产生后将此 Socket 标记为可读或可写 接着再把整个文件描述符集合拷贝回用户态里然后用户态还需要再通过遍历的方法找到可读或可写的 Socket然后再对其处理。所以对于 select 这种方式需要进行 2 次「遍历」文件描述符集合一次是在内核态里一个次是在用户态里 而且还会发生 2 次「拷贝」文件描述符集合先从用户空间传入内核空间由内核修改后再传出到用户空间中。select 使用固定长度的 BitsMap表示文件描述符集合而且所支持的文件描述符的个数是有限制的在 Linux 系统中由内核中的 FD_SETSIZE 限制 默认最大值为 1024只能监听 0~1023 的文件描述符。poll 不再用 BitsMap 来存储所关注的文件描述符取而代之用动态数组以链表形式来组织突破了 select 的文件描述符个数限制当然还会受到系统文件描述符限制。但是 poll 和 select 并没有太大的本质区别都是使用「线性结构」存储进程关注的 Socket 集合因此都需要遍历文件描述符集合来找到可读或可写的 Socket时间复杂度为 O(n)而且也需要在用户态与内核态之间拷贝文件描述符集合这种方式随着并发数上来性能的损耗会呈指数级增长。select/poll 实现及缺陷1. select 核心逻辑用固定长度 BitsMap存待检测 fd默认最多 1024 个全程 2 次拷贝用户态→内核态→用户态、2 次遍历内核遍历查事件用户态遍历找就绪 fd时间复杂度 O(n)fd 越多性能越差。2. poll 改进与缺陷用动态数组链表替代 BitsMap突破 1024 fd 限制但核心逻辑和 select 一致仍需 2 次拷贝、2 次遍历时间复杂度还是 O(n)高并发下性能损耗大。总结select/poll 本质都是「线性遍历全量拷贝」高并发场景下效率低epoll 用红黑树事件驱动优化了这两个核心问题。epoll先复习下 epoll 的用法。如下的代码中先用epoll_create 创建一个 epol l对象 epfd再通过 epoll_ctl 将需要监视的 socket 添加到epfd中最后调用 epoll_wait 等待数据。intssocket(AF_INET,SOCK_STREAM,0);bind(s,...);listen(s,...)intepfdepoll_create(...);epoll_ctl(epfd,...);//将所有需要监听的socket添加到epfd中while(1){intnepoll_wait(...);for(接收到数据的socket){//处理}}epoll 通过两个方面很好解决了 select/poll 的问题。第一点epoll 在内核里使用红黑树来跟踪进程所有待检测的文件描述字把需要监控的 socket 通过 epoll_ctl()函数加入内核中的红黑树里红黑树是个高效的数据结构增删改一般时间复杂度是 O(logn)。而 select/poll 内核里没有类似epoll 红黑树这种保存所有待检测的 socket 的数据结构所以 select/poll 每次操作时都传入整个 socket集合给内核而 epoll 因为在内核维护了红黑树可以保存所有待检测的 socket 所以只需要传入一个待检测的socket减少了内核和用户空间大量的数据拷贝和内存分配。第二点 epoll 使用事件驱动的机制内核里维护了一个链表来记录就绪事件当某个 socket 有事件发生时通过回调函数内核会将其加入到这个就绪事件列表中当用户调用 epoll_wait()函数时只会返回有事件发生的文件描述符的个数不需要像 select/poll 那样轮询扫描整个 socket集合大大提高了检测的效率。数据结构层面epoll 内核用红黑树保存所有待检测 fd增删改 O(logn)仅需传递单个fd 给内核select/poll无持久化结构每次需传递全量 fd 集合大量拷贝开销。检测机制层面epoll 是事件驱动内核维护就绪链表仅返回有事件的 fdselect/poll 需轮询全量 fd 检测状态fd 越多效率越低。epoll 边缘触发(ET) vs 水平触发(LT)水平触发LT只要 fd 满足就绪条件如内核有数据epoll_wait 就持续通知直到数据读完无需一次性读/写完毕兼容阻塞/非阻塞 fd是 epoll 默认模式。边缘触发ET仅当 fd 状态从未就绪变为就绪时通知一次需一次性读完/写完内核缓冲区数据必须搭配非阻塞 fd避免读/写空时阻塞减少 epoll_wait 调用次数效率更高。通俗类比LT快递箱一直发短信提醒取件直到取走为止ET快递箱只发一次取件短信不管是否取走都不再提醒。总结LT 更简单、不易漏数据适合简单场景ET 减少系统调用开销高并发场景更高效但编程复杂度高需循环读写非阻塞 fd。