第5章 锁与进程间通信(3)

目录

5.4 其他IPC机制

5.4.1 信号

5.4.2 管道和套接字

5.5 小结


本专栏文章将有70篇左右,欢迎+关注,查看后续文章。

5.4 其他IPC机制

5.4.1 信号

kill命令:

        作用:发送指定信号。

信号分为:

        传统32个信号。

        用于实时进程的RT新信号。

进程可屏蔽(阻塞)指定信号。

信号被屏蔽后,内核将信号放在待决列表上。而相同信号只会往待决列表放置一次。

所以不管发送了多少个相同信号,进程解除阻塞后,都只会收到一个信号。

进程无法阻塞SIGKILL信号。

        但init进程是特例。init进程会忽略收到的SIGKILL信号。

        因为init进程不能结束。

实现信号处理程序

struct        sigaction {

        void         (*sa_handler)(int);         //传统信号的处理函数。

        void         (*sa_sigaction)(int, siginfo_t *, void *);   //扩展信号的处理函数。

        sigset_t         sa_mask;         //屏蔽的信号集合。

        int                 sa_flags;         //信号处理行为标志,如SA_RESTART等。

};

sa_handler和sa_sigaction使用场景的区别:

        1. sa_handler:

                不需要获取信号的额外信息,处理简单。只有一个参数(信号编号)。

        2. sa_sigaction:

                需要获取信号的详细信息。如发送信号的进程PID,信号产生原因等。

1. sa_handler编程举例:

int         main() {

        struct sigaction         sa;

        sa.sa_handler   =   signal_handler;

        sigemptyset( &sa.sa_mask );

                //sa.sa_mask:用于指定要屏蔽的信号集合。

                //此处清空,表示不屏蔽任何信号。

        sigaddset(&sa.sa_mask,   SIGUSR1);         //屏蔽SIGUSR1信号。

        sigaction(SIGINT,   &sa,   NULL) ;

}

void   signal_handler(int   sig)

{

        ...

}

2. sa_handler编程举例:

int         main() {

        struct sigaction         sa;

        sa.sa_sigaction   =   signal_handler;

        sigemptyset(  &sa.sa_mask  );

        sa.sa_flags   =   SA_SIGINFO | SA_RESTART;

        sigaction(SIGSEGV,   &sa,   NULL);

}

void         signal_handler(int signum, siginfo_t *info, void *uctx)

{

}

函数参数:

        1. signum:信号编号。

        2. siginfo_t *:信号详细信息。内部包含:

                si_code:信号产生的原因。

                si_pid:发送信号的进程ID。

                si_uid:发送信号的用户ID。

                si_addr:某些信号(如SIGSEGV、SIGBUS),指向发生错误的内存地址。

        3. *uctx:参数上下文指针。

                作用:

                        保存信号发生时CPU寄存器状态,包括程序计数器PC、SP、通用寄存器等。

                通常为传参为NULL,即不需要上下文。

struct sigaction中成员 sa_flags 典型值:

        1. SA_SIGINFO:

                表示使用 siginfo_t 接收更多信号信息。

                此时使用struct sigaction的sa_sigaction为信号处理函数,而不是sa_handler。

        2. SA_RESTART:

                无SA_RESTART标志(默认):

                        当系统调用被信号中断,系统调用将返回EINTR。

                        此时程序需要检查返回值,若为EINTR则重新执行系统调用。

                有SA_RESTART标志:

                        当处理完中断信号后,被中断的系统调用将会自动重启。

                        而不返回 EINTR 错误。无需手动重新执行系统调用。

        3. SA_NOCLDSTOP:

                表示子进程收到暂停信号SIGSTOP时,不向父进程发送SIGCHLD信号。

                (通常子进程终止(不论正常,异常)时,会向父进程发送 SIGCHLD 信号)

        4. SA_NOCLDWAIT:

                表示对子进程的退出状态不感兴趣,子进程终止后,其资源立即释放,不成为僵尸进程。

信号的实现

待决信号(Pending Signal):已将信号发送给进程,但尚未被该进程处理的信号。

struct         task_struct {

        struct signal_struct             *struct;

        struct sighand_struct         *sighand;

        sigset_t                   blocked;         //位掩码,表示该进程阻塞的信号。

        struct sigpending    pending;

        unsigned long         sas_ss_sp;     //专用信号处理栈的基地址。

        size_t                      sas_ss_size;   //专用信号处理栈的大小。

}

成员介绍:

1. struct signal_struct   *struct;

        该进程的信号描述符。

                包含:

                        信号的默认行为、信号计数器等。

        通常同一进程组中的进程共享同一信号描述符。

2. struct sighand_struct     *sighand

        包含:

                不同信号的信号处理函数。

        通常父子进程会共享同一该结构,表示使用相同信号处理函数。

        struct         sighand_struct {

                atomic_t         count;         //共享该结构的进程数。

                struct k_sigaction         action[_NSIG];         //数组,包含每个信号对应的处理函数。

        }

        struct         k_sigaction {

                struct sigaction         sa;

        };

        sa.sa_handler = SIG_DFL; //使用该信号对应默认处理函数。

        不同信号,默认的处理函数不同,默认处理函数有:

                1. 忽略。

                2. 结束进程。

                3. 停止(设为TASK_STOPPED)。

                4. coredump。

3. struct sigpending         pending;

        该进程待处理的信号集合(即收到的未阻塞的信号)。

        当进程重新获得CPU运行时,查看该集合并处理其中信号。

        struct         sigpending {

                struct list_head         list;

                        //连接所有struct sigqueue实例,sigqueue包含待决信号详细信息。

                sigset_t         signal;         //表示待决信号的位掩码。

        };

        struct         sigqueue {

                siginfo_t         info;         //存储待决信号的详细信息。如下

        }

        typedef struct         siginfo {

                int         si_signo;         //信号编号。

                int         si_errno;         //错误编号(仅当si_code为SIGILL、SIGFPE、SIGSEGV、SIGBUS时有效)。

                int         si_code;         //信号代码。

                pid_t     si_pid;           //发送信号的进程ID。

                uid_t      si_uid;         //发送信号的用户ID。

                int         si_status;

                        //子进程的退出状态(仅当si_code为SIGCHLD时有效)

                clock_t         si_utime;

                        //进程的用户CPU时间(仅当si_code为SIGCHLD时有效)

                clock_t         si_stime;

                        //进程的系统CPU时间(仅当si_code为SIGCHLD时有效)

                void               *si_addr;

                        //发生段错误的地址(仅当si_code为SIGSEGV/SIGBUS/SIGILL/SIGFPE时有效)

                int                 si_fd;

                        //产生信号的文件描述符(仅当si_code为SIGIO、SIGPOLL时有效)

                void                 *si_call_addr;

                        //发生硬件错误的地址(仅当si_code为SIGTRAP时有效)

                int                     si_syscall;

                        //发生系统调用错误的系统调用编号(仅当si_code为SIGSYS时有效)

                unsigned int         si_arch;

                        // 发生硬件错误的CPU体系架构(仅当si_code为SIGBUS、SIGFPE、SIGILL、SIGSEGV时有效)

} siginfo_t;

通常信号处理函数使用进程的用户栈,也可用sigaltstack函数设置专用栈。

sigaltstack系统调用:

        作用:

                设置一个线程的备用信号栈。

        使用场景:

                1. 备用信号栈可处理栈溢出,如错误报告、资源释放等。

                2. 确保信号处理函数不影响主调用栈或其他线程。

                3. 某些信号处理函数需要大量栈空间,如SIGSEGV段错误。

信号相关系统调用

注意:不是shell命令

1. kill:

        向进程组的所有进程发送一个信号。

2. sigpending:

        检查是否有待决信号。

5.4.2 管道和套接字

管道:

        举例:ls | grep wo

        实现: 使用虚拟文件系统对象。

fork/clone进程时,也将复制管道。所以父子进程可通过管道通信。

无名管道:

        创建函数:

                int pipe(int pipefd[2]);

        使用对象:

                父子进程间通信。半双工。

        文件系统中没有对应无名管道文件。

        使用方法:

                1. pipe()。返回两个文件描述符(一个用于读,一个写)

                2. fork()

                3. 父进程读,子进程写(反之亦可)

有名管道:

        创建函数:int mkfifo(const char *pathname, mode_t mode)

        使用对象:任意进程间通信。

        文件系统中存在有名管道文件。

        int         mkfifo(const char *pathname, mode_t mode)

                pathname:需要创建管道文件的文件名。

                mode:管道的权限。

        

        后续可基于该pathname文件进行open(), read(), write()等实现进程间通信。

5.5 小结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/663640.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JavaWeb笔记整理+图解——Filter过滤器

欢迎大家来到这一篇章——Filter过滤器 监听器和过滤器都是JavaWeb服务器三大组件(Servlet、监听器、过滤器)之一,他们对于Web开发起到了不可缺少的作用。 ps:想要补充Java知识的同学们可以移步我已经完结的JavaSE笔记,里面整理了大量详细的知识点和图解,可以帮你快速掌…

[SWPU 2019]神奇的二维码、buuctf部分web题

目录 [SWPU 2019]神奇的二维码 [LitCTF 2023]Http pro max plus [SWPUCTF 2021 新生赛]finalrce ​[鹏城杯 2022]简单包含 [SWPUCTF 2022 新生赛]ez_ez_php(revenge) [GKCTF 2020]cve版签到 cve-2020-7066: [SWPU 2019]神奇的二维码 解码看看,是…

让AI学相机对焦: Learning to AutoFocus

前言 分析来自谷歌发表在 CVPR 2020 上的论文 Learning to Autofocus :https://arxiv.org/pdf/2004.12260 目前网上对这篇论文的分析较少,有的分析并没有指出关键点,如:论文解读: Learning to AutoFocus-CSDN博客&am…

Iphone自动化指令每隔固定天数打开闹钟关闭闹钟(一)

注意:因为是第一次用iphone的快捷指令,不是很明白,所以之后多次运行发现有bug,所以快捷指令部分在下一章重新写,我用两个日期测试了,没问题,这一章可以当做熟悉快捷指令的一些操作用&#xff0c…

算法学习笔记(7.3)-贪心算法(最大切分乘问题)

目录 ##问题描述 ##问题思考 ##贪心策略确定 ##代码实现 ##时间复杂度 ##正确性验证 ##问题描述 给定一个正整数 𝑛 ,将其切分为至少两个正整数的和,求切分后所有整数的乘积最大是多少 ##问题思考 假设我们将 𝑛 切分为 &…

Memory测试工具-stressapptest详解

✨前言: stressapptest 是一个用于在各种系统组件上施加压力的工具,特别专注于内存和CPU。通过运行各种模式的访问测试,stressapptest 旨在模拟高负载下的系统行为,并帮助发现潜在的错误,比如硬件故障、过热或系统组件…

第二证券股市资讯:重磅信号!五大利好来袭!

商场中,向好的变化正在发生。 5月29日,商场迎来多则重磅利好: 一、IMF上调本年我国经济增加预期至5%; 二、国务院印发《2024-2025年节能降碳举动计划》,光伏、新动力轿车等多个职业迎来方针利好&#xf…

Linux中部署MinIO

Linux中部署MinIO 下载MinIO可执行程序: wget https://dl.min.io/server/minio/release/linux-amd64/minio 添加执行权限: chmod x minio 创建存储目录,例如/data: mkdir -p /data 运行MinIO服务器,需要设置MIN…

Java设计模式 _行为型模式_访问者模式

一、访问者模式 1、访问者模式 访问者模式(Visitor Pattern)是一种行为型模式。它允许在不修改已有类结构的情况下,向类中添加新的操作。访问者模式通过将操作封装在一个访问者对象中,使得可以在不改变各个元素类的前提下&#x…

【信息学奥赛】在一个包含N个整数的数组中找到第一个质数

【信息学奥赛】在一个包含N个整数的数组中找到第一个质数 💖The Begin💖点点关注,收藏不迷路💖 编写一个函数,用于在一个包含N个整数的数组中找到第一个质数,若有则返回函数的地址;否则返回NUL…

fps游戏如何快速定位矩阵

fps游戏如何快速定位矩阵 矩阵特点: 1、第一行第一列值的范围在**-1 ---- 1**之间&#xff0c;如果开镜之后值会变大。 2、第一行第三列的值始终为 0。 3、第一行第四列 的值比较大 &#xff0c; >300或者**<-300**。 根据这三个特点&#xff0c;定位矩阵已经足够了…

Javaweb第九次作业

采用XML映射文件的形式来映射sql语句&#xff1b;采用动态sql语句的方式&#xff0c;实现条件查询的分页。 controller Slf4j RestController RequestMapping("supermarket111") public class SupermarketFenyeController {AutowiredSupermarketFenyeService super…

flutter开发实战-下拉刷新继续下拉路由进入活动页面实现

flutter开发实战-下拉刷新继续下拉路由进入活动页面实现 很多应用都有首页通过下拉刷新&#xff0c;继续下拉进入新的活动会场进入方式。在Flutter中&#xff0c;也可以通过pull_to_refresh来实现控制刷新页&#xff0c;继续下拉进入新的活动会场页面 一、引入pull_to_refres…

svg实现一个圆形以及方形的环形进度条

1. svg实现圆形进度条 效果图&#xff1a; 1. 写个假接口&#xff1a; let res {curLegendList: [{ progress: "87", name: "进度1",color:"#00fe41" },{ progress: "66", name: "进度2" ,color:"orange"},{ p…

HarmonyOS鸿蒙学习笔记(25)相对布局 RelativeContainer详细说明

RelativeContainer 简介 前言核心概念官方实例官方实例改造蓝色方块改造center 属性说明参考资料 前言 RelativeContainer是鸿蒙的相对布局组件&#xff0c;它的布局很灵活&#xff0c;可以很方便的控制各个子UI 组件的相对位置&#xff0c;其布局理念有点类似于android的约束…

OpenPCDet

一.简介 源码链接&#xff1a; https://github.com/open-mmlab/OpenPCDethttps://github.com/open-mmlab/OpenPCDet OpenPCDet 是一套基于PyTorch实现的点云3D目标检测代码库。&#xff08;也是个框架&#xff09; 设计思想&#xff1a;点云数据集&#xff08;KITTI、NuSce…

pytorch学习笔记2

首先如果遇到conda找不到包&#xff0c;pip老是超时的情况建议添加一下镜像源 conda的 conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/ cond…

【C++ | 类】类和对象

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; ⏰发布时间⏰&#xff1a; 本文未经允许…

收银系统源码-千呼新零售2.0【智慧供应链】

千呼新零售2.0系统是零售行业连锁店一体化收银系统&#xff0c;包括线下收银线上商城连锁店管理ERP管理商品管理供应商管理会员营销等功能为一体&#xff0c;线上线下数据全部打通。 适用于商超、便利店、水果、生鲜、母婴、服装、零食、百货等连锁店使用。 详细介绍请查看下…

为什么String要被设置为不可变的

为什么设置为不可变的 Java 中将 String 设计为不可变的原因有多个&#xff0c;主要涉及到安全、效率、同步和设计哲学 缓存 在我们的JVM中&#xff0c;单独开辟了一个空间来存储Java字符串&#xff0c;就是字符串池 String s1"1234"; String s2"766"; …