进程线程考核
计数信号量概念初值为大于 1 整数的信号量可管控多个同类临界资源。原理申请资源计数减 1P操作释放资源计数加 1V操作计数为 0 时进程阻塞等待。作用控制多进程 / 线程访问有限数量资源实现同步与资源限流。特点允许多个任务同时使用资源超出上限则排队等候。计数信号量的主要作用控制多进程 / 线程访问有限数量资源实现同步与资源限流。进程属于这个终端就会有tty1、TTY7这样的标识终端里启动的第一个进程叫会话组组长线程的属性两种线程的属性结合式joinable系统默认的属性分离式detached设置参数取值PTHREAD_CREATE_JOINABLE默认无需设置PTHREAD_CREATE_DETACHED回收手动回收用pthtread_join必须回收自动回收不能被join回收特征能够被其他线程回收资源和杀死在其他线程回收之前它的存储资源栈是不释放的不能被其他线程回收或杀死它的存储器资源在它终止时由系统回收结合式joinable和分离式detached结合式的线程需要回收使用phread_join函数回收必须回收任意两个线程可以相互回收父回收子子回收父不回收会造成资源泄漏产生线程僵尸长期运行会耗尽系统资源导致无法创建新线程内存/资源泄漏 资源被占用、不归还不是数据消失分离式不需要回收系统自动回收不能被join 无需手动回收如何设置线程的属性设置分离式线程的两种方法一种被赶走的创建之后再修改的方式一结合态线程创建后通过pthread_detach转为分离态#include pthread.h #include stdio.h void *thread_func(void *arg) { printf(结合态转分离态线程运行\n); pthread_exit(NULL); } int main() { pthread_t tid; // 1. 创建默认结合态线程 pthread_create(tid, NULL, thread_func, NULL); // 2. 将线程转为分离态 pthread_detach(tid); // 主线程休眠避免提前退出仅演示用 sleep(1); return 0; }另一种自己设置的通过一个线程函数方式一通过线程属性创建时设置分离态#include pthread.h #include stdio.h void *thread_func(void *arg) { printf(分离态线程运行\n); pthread_exit(NULL); } int main() { pthread_t tid; pthread_attr_t attr; // 1. 初始化线程属性 pthread_attr_init(attr); // 2. 设置属性为分离态 pthread_attr_setdetachstate(attr, PTHREAD_CREATE_DETACHED); // 3. 创建分离态线程 pthread_create(tid, attr, thread_func, NULL); // 4. 销毁属性对象 pthread_attr_destroy(attr); // 主线程休眠避免提前退出仅演示用 sleep(1); return 0; }互斥与同步互斥是一次只能由一个进程去执行资源不能有其他的线程去执行属于先到先得没有先后顺序同步是协作执行资源没有冲突可以按顺序执行这个进程有先后顺序信号量信号量 sem_t:是一个结构体盆放资源用sem_init:初始化信号量P操作申请资源往哪个盆拿资源V操作释放资源往哪个盆放资源ld 链接错误链接阶段进程间的通信方式方式无名管道半双工面向字节流只用于亲缘间的进程位于进程共享内存或线程栈有名管道半双工面向字节流亲缘与非亲缘都支持位于进程共享内存或线程栈信号异步有优先级用于简单通知不能传输大量数据不传数据只发通知、中断进程、异步通知事件消息队列全双工面向消息每条消息独立自带类型可按消息类型精准读取内核持久化进程退出消息队列依旧保留数据直到手动删除共享内存无内置同步效率最高多个进程映射同一块物理内存数据直接读写无拷贝必须配合互斥锁/信号量实现同步互斥防止竞态内核信号量同步不传输数据主要作用是进程/线程同步、互斥访问共享资源控制进程对共享资源的访问本质是计数器内核套接字全双工支持面向连接TCP、无连接(UTP功能最强支持本地跨网络通信不同主机之间的通信进程线程分配资源资源分配的最小单元给分配资源一定是给进程分配资源CPU调度的最小单元时间片是给线程分配空间独立的地址空间资源共享所在进程地址的空间资源开销大创建进程\切换进程小通信方式依赖IPC六种通信方式直接共享数据配合同步机制即可安全性进程之间相互隔离安全性高独立性高一个线程崩溃整个进程退出安全性低应用场景进程适用于任务间强调安全性高高隔离性的场景如后台服务、第三方插件、沙箱程序防止单个模块异常拖垮了整体适用于独立性要求高的场景如独立程序/客户端软件浏览器、编辑器、播放器、终端每个进程都是相互独立的互不干扰适用于多程序并行运行的场景同时运行多个不同软件、服务适用于需要独占独立资源的场景任务需要独占内存、端口、文件等资源共享内存 vs 管道pipe效率对比与场景差异一、为什么共享内存的通信效率更高核心原因是数据拷贝次数的差异1. 管道pipe的数据流动过程管道是内核缓冲区实现的数据需要经过两次拷贝用户态 → 内核态写进程调用write()数据从用户缓冲区拷贝到管道的内核缓冲区。内核态 → 用户态读进程调用read()数据从内核缓冲区拷贝到自己的用户缓冲区。每次读写都必须陷入内核态涉及上下文切换和两次数据拷贝开销较大。2. 共享内存的数据流动过程共享内存是多个进程直接映射到同一块物理内存数据流动无需经过内核写进程直接在共享内存地址写入数据用户态操作无系统调用。读进程直接从共享内存地址读取数据同样是用户态操作。整个过程没有数据拷贝也没有用户态 / 内核态的切换因此效率远高于管道。特性管道pipe共享内存适用进程匿名管道仅支持亲缘进程命名管道支持无亲缘进程所有进程无亲缘限制通信方向半双工单向双向通信需两根管道全双工双向读写数据形式面向字节流无消息边界任意数据结构可自定义协议同步支持自带读写阻塞机制无内置同步需配合信号量 / 互斥锁适用场景简单的、低频次的数据传递如父子进程间的命令交互高频、大数据量传输如视频流、缓存数据、服务间高性能通信应用场景线程适用于并发任务处理如服务器web服务、接口服务海量请求并发用于多线程快速处理适用于同一程序内多分工如一个程序同时做数据接收、数据计算、日志打印适用于频繁创建销毁任务如爬虫、批量读写文件、交替执行任务如交替打印AB适用于大量数据共享如多任务需要频繁读取同一份数据线程共享内存更高效pthread: //p是可移植的意思;通用接口所有操作系统都可以用系统调用是第三方接口生产者消费者模型有货架:顾客和店员只有一个顾客可以去拿货物不能同时去拿货架上的东西且只能是在不满的情况下操作互斥同一个时间什么东西能把互斥锁上用临界资源临界资源多个线程或进程访问的资源且同一时刻只能一个人访问资源临界区访问临界资源的代码称为临界区什么是消息队列POSIX消息队列什么是POSIX消息队列是一种用于进程间通信IPC的技术它允许不同进程间通过发送和部分接收消息来进行通信。POSIX消息队列是基于POSIX标准的一部分旨在提供跨平台的兼容性和一致性为什么要有信号系统要求进程有随时访问外界信号的能力随后做出反应主要有一下几个用途异步通知:允许一个进程或线程在不间断其正常执行的情况下接收通知以便采取适当的措施进程间通信进程可以使用信号来通知其他进程发生的事件这对多任务协作非常有帮助异常处理操作系统可以使用信号来通知进程发生了异常情况如除以零或无效内存访问以帮助进程处理这些异常用户交互:用户可以通过键盘快捷键或类似的输入方式发送信号给正在运行的进程以请求特定操作资源泄漏泄漏的是什么结合式线程不回收会造成资源泄漏1、泄漏PID号2、内核TCB线程控制块这个就是资源泄漏3、栈内存泄漏栈的内存没回收一直强占在内存消耗空间即结合式线程没回收会造成资源和内存的双方面泄漏长期导致耗尽内存、程序崩溃或无法创建新线程有名管道与信号量都是使用共享内存它们实现共享内存的途径是怎么实现的有什么区别简述线程池的概念与作用作用从功能上的两点出发1、限制创建数量避免占用大量资源和创建线程而带来的开销2、不用创建和销毁节省了对线程的繁琐操作缩短了运行时间重复使用这个线程提供运行效率信号灯级是进程间的信号而信号量是进程间的线程间有哪些资源是共享的哪些资源是独有的共享的资源地址空间代码段、数据段、堆文件描述符、信号处理方式、当前工作目录用户ID、组ID、进程ID1、全局变量所以线程都可以访问和修改的变量2、静态变量所以线程都可以访问和修改的静态变量3、共享内存通过共享内存区域可以在多个线程间进行数据传递和共享独占线程ID线程栈1、局部变量仅在当前线程中可见和使用的变量2、栈空间每个线程都有自己独立的栈空间存储函数调用时的参数3、寄存器每个线程都有自己独立的寄存器用于存储函数临时变量和计算结果等。4、栈帧每个线程的函数调用会生成一个栈帧用于存储函数的参数、返回地址等信息全局变量怎么设置volatile定义entern 变量名多线程全局变量volatilevolatile int flag 0;volatile 用于多线程共享变量禁止编译器优化保证每次都读到内存里的最新值。简述写实拷贝技术 与 计数技术写时拷贝1.定义多个进程共享同一块物理内存只映射虚拟地址不会立刻复制内存延时拷贝2.触发时机当任意进程修改数据写操作瞬间系统才会为这个进程复制一份独立内存各自修改互不干扰。3.作用减少内存占用、降低拷贝开销提升系统运行效率使用场景Linux fork创建子进程默认使用写时拷贝计数信号量 简述1.概念初始为大于1整数的信号量可管控多个同类临界资源2.原理申请资源记数减1 释放资源计数加1计数为0时进程阻塞等待3.作用控制多进程/线程访问有限数量资源实现同步与资源限流4.特点运行多个任务同时使用资源超出上限排队等候计数信号量计数计的是线程的资源数的剩余数量信号量使多个线程可以访问共享资源而计数值可以控制共享资源的并发访问数量信号量弥补了互斥锁只能一个线程访问资源而在多线程并发资源的不足一、定义计数信号量是一种用于多线程、多进程同步的机制本质是一个非负整数计算器用来控制同时访问共享资源的最大并发数它既可以实现互斥也可以实现同步二、核心原理1、信号量的值代表可用资源数量2、p操作wait/sem_wait申请资源信号量-1若值 0,进程/线程阻塞等待3.V操作post/sem_post释放资源信号量1若有等待者唤醒一个三、特点可以允许多个线程同时进入临界区互斥锁只允许1个计数信号量允许N个用于控制资源并发访问数量如限制最多5个连接总结:计数信号量是一个非负整数通过P/V操作控制同时访问资源的线程数量实现同步与互斥同步访问、异步访问、互斥访问信号量实现线程的同步盆——资源池——信号量球——资源数——人——线程把球夹起来——P操作——申请资源把球加起来放球放到另一个人的盆中——V操作——释放资源当资源数为负数时如-2时代表这个进程需要等待两个球但是球并不能为负数实际情况只能代表0而设置的资源数为0是它的资源数不少也不多但也是等待状态一、为什么需要僵尸态1. 概念子进程先于父进程退出但父进程未调用wait/waitpid读取子进程退出状态子进程就进入僵尸态Z。 子进程代码、数据、栈资源全部释放仅保留进程控制块 PCB存退出码、运行状态等信息。2. 存在意义核心原因保存退出信息父进程可能需要知晓子进程的退出原因、返回值、异常信号等内核必须暂时保留 PCB 信息供父进程查询。遵循进程资源回收规则Linux 规定子进程的退出状态必须由父进程负责回收内核不能直接丢弃因此用僵尸态临时占位。防止信息丢失若直接彻底销毁进程父进程后续想获取子进程运行结果将无从查询。补充危害大量僵尸进程会占用 PID、内核 PCB 资源导致系统无法创建新进程。二、僵尸子进程的回收方法方法 1父进程主动调用wait()/waitpid()最基础父进程阻塞 / 轮询等待子进程退出主动获取退出状态内核随即释放僵尸进程 PCB。wait(NULL)阻塞等待任意子进程退出一次性回收。waitpid()可指定回收某个子进程也可非阻塞轮询回收方法 2父进程注册SIGCHLD信号处理函数工程常用子进程退出时会向父进程发送SIGCHLD信号。 父进程捕获该信号在信号处理函数中执行wait/waitpid批量回收所有僵尸子进程。 特点异步回收不阻塞父进程正常业务。方法 3让父进程先退出子进程被init进程收养简单临时方案父进程先结束其子进程含僵尸进程会被PID1 的 init/systemd 进程收养。init 进程会自动定期回收孤儿子进程、僵尸进程。 缺点仅适用于简单场景无法让原父进程获取子进程退出状态。方法 4创建会话 / 守护进程手动托管子进程将子进程脱离原终端与父进程所在会话交由系统进程托管由系统负责回收多用于后台服务。fork函数如何使用为何fork的返回值如此设计使用创建一个新的子进程调用fork一次返回两次两个返回值1、让父子进程能区分自己2、让父进程获得子进程 PID方便管理3、一次调用完成创建 区分高效简洁1. 让父子进程能区分自己子进程返回 0→ 知道自己是子进程父进程返回子进程 PID→ 知道子进程是谁2. 子进程无法获取自己的 PID必须靠父进程告诉父进程必须拿到子进程 PID方便管理才能wait 等待子进程杀死子进程发送信号3. 一个函数调用同时完成两件事创建进程区分父子、让父进程拿到子进程 ID2、fork函数如何使用为何fork的返回值如此设计答fork函数调用一次返回两次调用一次时创建并区分了父子进程父进程的返回值是子进程的PID而子进程的返回值是0这样设计的目的是能够区分父子进程相互独立便于父进程监管子进程高效简洁虚拟地址通过MMU获取PID号和虚拟地址这个信息找到对应映射的物理地址位置TLB快表相当于一个目录用来快速查询物理地址的索引表找到真实位置1、防止修改真实的物理地址随意访问保护物理地址防止病毒软件的产生再返回值2、节省内存零散的物理内存映射到虚拟地址为连续的空间3、如果内存不够会使用一部分磁盘空间作为物理内存机械硬盘改成固态硬盘提示加载速度32位操作系统——32根地址总线64位——64根地址总线进程消耗内存的资源消耗时间片CPU给进程分配运行的时间引用计数技术Reference Counting核心定义一种资源生命周期管理技术通过计数器记录资源被引用的次数实现自动释放常与写时拷贝配合。1. 核心思想为每份共享资源额外维护一个整数计数器资源被新引用如拷贝、赋值计数器 **1**。引用解除如析构、销毁计数器 **-1**。计数器减为 0无任何引用立即释放资源内存、文件句柄等。2. 工作流程以 C 共享字符串为例创建字符串对象分配内存引用计数 1。拷贝构造 / 赋值仅拷贝指针引用计数 1如变为 2不复制数据。某对象修改数据触发写时拷贝原计数 **-1**变为 1新副本计数 1。对象析构引用计数 - 1若变为 0释放字符串内存。3. 关键特点优点自动管理内存、避免泄漏、防止重复释放实现简单配合 COW 提升效率。缺点循环引用如 A 引用 B、B 引用 A导致计数永不为 0内存泄漏频繁增减计数有轻微性能开销。三、两者关系与区别关系引用计数是写时拷贝的基础COW 靠引用计数判断资源是否共享计数 1 则共享需拷贝1 则独占无需拷贝。区别写时拷贝侧重拷贝时机优化读共享、写复制解决性能与内存浪费问题。引用计数侧重资源生命周期管理自动释放解决内存泄漏与重复释放问题。互斥锁死锁产生的原因如何避免原因线程互相持有对方需要的锁、循环等待同时竞争同一把锁单次线程重复加同一把锁递归锁除外。避免统一锁的申请顺序、减少嵌套加锁、限时等待锁。产生的四个条件1.请求与保持占用与等待已经有了资源又去申请资源且自己的资源不释放2.互斥条件3.不可剥夺条件4.循环等待条件A等B、B等C、C等A