1.Linux进程管理:深入task_ struct字段
2.从 pm2 看 node 多进程管理(一):进程创建
3.Linux内核:进程管理——自旋锁
4.Linux内核源码分析:Linux进程描述符task_ struct结构体详解
5.ZMQ源码详细解析 之 进程内通信流程
6.nginx源码分析--master和worker进程模型
Linux进程管理:深入task_ struct字段
深入解析Linux进程管理:task_struct字段探索
高怡香、徐晗博,管理管理西安邮电大学研一在读,源码源码操作系统和Linux内核爱好者,进程进程热衷于探索操作系统底层工作原理和内核编程。管理管理
通过top命令,源码源码源码分析方案可以监视即时的进程进程进程状态,便于观察以特定用户身份运行的管理管理进程。按u键输入用户名,源码源码只显示相关进程信息。进程进程按h键获取帮助。管理管理
task_struct结构体是源码源码操作系统用于管理进程的重要组成部分,在/include/linux/sched.h中定义。进程进程每个进程对应一个task_struct实例。管理管理
Linux内核源码分析之task_struct结构分析
剖析Linux内核进程管理
Linux内核,源码源码进程调度器的实现,完全公平调度器 CFS
免费学习地址:Linux C/C++开发(后端/音视频/游戏/嵌入式/高性能网络/存储/基础架构/安全)
需要C/C++ Linux服务器架构师学习资料加qun 获取(资料包括C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,微视去水印源码K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等),免费分享
通过遍历系统进程链表,访问每个进程的PCB(task_struct),可以打印进程相关属性。
task_struct成员众多,重点了解:进程ID、状态、优先级、时间切片、调度器等。
find_get_pid()与pid_task()接口函数用于快速查找指定PID对应的进程结构体。
打印子进程和兄弟进程,理解parent/children/sibling三者关系,实现代码需考虑进程实际存在。
设置两个内核模块参数,实现打印特定进程的子进程信息或兄弟进程信息。
eBPF技术应用于task_struct字段打印,对libbpf-bootstrap示例文件进行学习与实践。
实验总结,复习链表与模块传参知识,提升编程能力。解决函数版本问题,学习新函数并应用。蚂蚁庄园 php源码在进程亲属关系理解上获得指导,成功实现打印。
从 pm2 看 node 多进程管理(一):进程创建
pm2 是 Node 社区中领先的进程管理工具。本文基于 pm2 v4.5.0 的源码,聚焦于功能层面,深入探讨其模块结构和进程创建流程。
pm2 的核心模块包含 API 类的实例,API 初始化时会设置默认配置、用户传入配置,并生成 Client 实例。pm2 多进程管理支持两种创建入口:脚本文件或 JSON 配置,依据用户输入自动选择。
在系统中无 pm2 创建的守护进程时,使用 cluster 模式执行脚本后,pm2 将执行如下操作:确定进程创建入口、创建守护进程、建立与 rpc 服务的连接、启动工作进程和执行应用。
确定进程创建入口时,pm2 会根据脚本文件或 JSON 配置选择启动方式。_startJson 方法作为入口,初始化配置并启动应用进程。
创建守护进程前,pm2 调用 Client.executeRemote('getMonitorData') 方法获取系统存活进程信息。若无守护进程,pm2 优先创建守护进程,通过创建 rpc.Client 实例与 rpc.Server 连接,实现与 Daemon 模块交互。elf反编译源码在 Daemon 初始化时,pm2 会根据传入参数判断是否直接启动或作为守护进程启动。
pm2 使用 child_process.spawn 启动 Daemon 进程,之后绑定 PubEmitter 和 RepSocket socket,实现与 Client 和 God 模块的通信。一旦 socket 连接成功,pm2 会通知 Client 建立与 RepSocket server 的连接,供后续操作。
建立好 Daemon 进程和 rpc 连接后,pm2 通过 Client.executeRemote('prepare') 方法创建新进程,实现与 God 模块的直接调用。
pm2 支持 cluster 和 fork 模式启动应用进程,具体实现细节不在本文赘述。值得注意的是,pm2 提供了优雅启动功能,允许应用在依赖环境准备完成后才启动,只需在准备就绪后向 pm2 发送 'ready' 消息。
pm2 从头创建进程的一般过程可总结为:确定入口、创建守护进程、建立 rpc 连接、启动应用进程。此流程确保了高效、灵活的进程管理。
Linux内核:进程管理——自旋锁
Linux内核中的进程管理涉及重要机制——自旋锁,它用于保护临界资源的并发访问。自旋锁的工作原理类似于内存中一个flag变量,表示锁的状态。当flag为0时,雇工网php源码表示未锁定,线程可获取并操作临界资源,完成后设置flag为1释放锁。若获取时flag已为1,线程会进入循环等待,直至flag变为0。在多核环境中,自旋锁可能导致无序竞争,为解决这一问题,它类似餐馆取号机制,确保先等待的线程优先获得锁。
Linux内核中提供了不同类型的自旋锁操作函数,如spin_lock、spin_lock_irq等,针对中断处理也有相应处理函数。对于UP系统和SMP系统,自旋锁的实现有差异,UP系统相对简单,而SMP系统涉及更复杂的预抢占控制和体系结构特定的加锁实现。例如,SMP系统中,加锁函数调用流程涉及preempt_disable和arch_spin_lock等步骤。
自旋锁源码分析显示,加锁时,未获锁的线程会陷入休眠,长时间等待,影响CPU效率。而在解锁时,由于不存在竞争,无需原子操作。在arm和arm架构中,自旋锁的结构和实现略有不同,但核心原理是一致的,即维护一个owner和next值,以实现有序的临界资源访问。
最后,对于想要深入学习Linux内核的读者,有相关的技术交流群和资源包,包括视频教程、电子书和实践项目,可通过链接获取。通过这些资源,可以系统地学习Linux内核的进程管理,包括自旋锁在内的核心机制。
Linux内核源码分析:Linux进程描述符task_ struct结构体详解
Linux内核通过一个task_struct结构体来管理进程,这个结构体包含了一个进程所需的所有信息。它定义在include/linux/sched.h文件中,包含许多字段,其中state字段表示进程的当前状态。常见的状态包括运行、阻塞、等待信号、终止等。进程状态的切换和原因可通过内核函数进行操作。PID是系统用来唯一标识正在运行的每个进程的数字标识,tgid成员表示线程组中所有线程共享的PID。进程内核栈用于保存进程在内核态执行时的临时数据和上下文信息,通常为几千字节。内核将thread_info结构与内核态线程堆栈结合在一起,占据连续的两个页框,以便于访问线程描述符和栈。获取当前运行进程的thread_info可通过esp栈指针实现。thread_info结构包含task字段,指向进程控制块(task_struct)。task_struct结构体的flags字段用于记录进程标记或状态信息,如创建、超级用户、核心转储、信号处理、退出等。而real_parent和parent成员表示进程的亲属关系,用于查找和处理进程树中的亲属关系。
ZMQ源码详细解析 之 进程内通信流程
ZMQ进程内通信流程解析
ZMQ的核心进程内通信原理相当直接,它利用线程间的两个队列(我称为pipe)进行消息交换。每个线程通过一个队列发送消息,从另一个队列接收。ZMQ负责将pipe绑定到对应线程,并在send和recv操作中通过pipe进行数据传输,非常简单。
我们通过一个示例程序来理解源码的工作流程。程序首先创建一个简单的hello world程序,加上sleep是为了便于分析流程。程序从`zmq_ctx_new()`开始,这个函数创建了一个上下文(context),这是ZMQ操作的起点。
在创建socket时,如`zmq_socket(context, ZMQ_REP)`,实际调用了`ctx->create_socket`,socket类型决定了其特性。rep_t是基于router_t的特化版本,主要通过限制router_t的某些功能来实现响应特性。socket的创建涉及到诸如endpoint、slot和 mailbox等概念,它们在多线程环境中协同工作。
进程内通信的建立通过`zmq_bind(responder, "inproc://hello")`来实现,这个端点被注册到上下文的endpoint集合中,便于其他socket找到通信通道。zmq的优化主要集中在关键路径上,避免对一次性操作过度优化。
接下来的recv函数是关键,即使没有连接,它也会尝试接收消息。`xrecv`函数根据进程状态可能阻塞或返回EAGAIN。recv过程涉及`msg_t`消息的处理,以及与`signaler`和`mailbox`的交互,这些组件构成了无锁通信的核心。
发送端通过`connect`函数建立连接,创建连接通道,并将pipe关联到socket。这个过程涉及无锁队列的管理,如ypipe_t和pipe_t,以及如何均衡发送和接收。
总结来说,ZMQ进程内通信的核心是通过管道、队列和事件驱动机制,实现了线程间的数据交换。随着对ZMQ源码的深入,会更深入理解这些基础组件的设计和工作原理。
nginx源码分析--master和worker进程模型
一、Nginx整体架构
正常执行中的nginx会有多个进程,其中最基本的是master process(主进程)和worker process(工作进程),还可能包括cache相关进程。
二、核心进程模型
启动nginx的主进程将充当监控进程,主进程通过fork()产生的子进程则充当工作进程。
Nginx也支持单进程模型,此时主进程即是工作进程,不包含监控进程。
核心进程模型框图如下:
master进程
监控进程作为整个进程组与用户的交互接口,负责监护进程,不处理网络事件,不负责业务执行,仅通过管理worker进程实现重启服务、平滑升级、更换日志文件、配置文件实时生效等功能。
master进程通过sigsuspend()函数调用大部分时间处于挂起状态,直到接收到信号。
master进程通过检查7个标志位来决定ngx_master_process_cycle方法的运行:
sig_atomic_t ngx_reap;
sig_atomic_t ngx_terminate;
sig_atomic_t ngx_quit;
sig_atomic_t ngx_reconfigure;
sig_atomic_t ngx_reopen;
sig_atomic_t ngx_change_binary;
sig_atomic_t ngx_noaccept;
进程中接收到的信号对Nginx框架的意义:
还有一个标志位:ngx_restart,仅在master工作流程中作为标志位使用,与信号无关。
核心代码(ngx_process_cycle.c):
ngx_start_worker_processes函数:
worker进程
worker进程主要负责具体任务逻辑,主要关注与客户端或后端真实服务器之间的数据可读/可写等I/O交互事件,因此工作进程的阻塞点在select()、epoll_wait()等I/O多路复用函数调用处,等待数据可读/写事件。也可能被新收到的进程信号中断。
master进程如何通知worker进程进行某些工作?采用的是信号。
当收到信号时,信号处理函数ngx_signal_handler()会执行。
对于worker进程的工作方法ngx_worker_process_cycle,它主要关注4个全局标志位:
sig_atomic_t ngx_terminate;//强制关闭进程
sig_atomic_t ngx_quit;//优雅地关闭进程(有唯一一段代码会设置它,就是接受到QUIT信号。ngx_quit只有在首次设置为1时,才会将ngx_exiting置为1)
ngx_uint_t ngx_exiting;//退出进程标志位
sig_atomic_t ngx_reopen;//重新打开所有文件
其中ngx_terminate、ngx_quit、ngx_reopen都将由ngx_signal_handler根据接收到的信号来设置。ngx_exiting标志位仅由ngx_worker_cycle方法在退出时作为标志位使用。
核心代码(ngx_process_cycle.c):