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

news2024/11/16 1:33:00

目录

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 小结

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【机器学习】Samba-CoE实现高效推理部署

Samba-CoE:突破AI内存墙,实现高效推理部署 一、引言二、Samba-CoE系统概述三、突破AI内存墙的关键技术流数据流三层内存系统 四、Samba-CoE的推理部署与优化动态模型切换资源优化分配性能加速 五、代码实例与实现细节六、结语 一、引言 随着人工智能技术…

es的总结

es的collapse es的collapse只能针对一个字段聚合(针对大数据量去重),如果以age为聚合字段,则会展示第一条数据,如果需要展示多个字段,需要创建新的字段,如下 POST testleh/_update_by_query {…

2024-05-31 blue-VH-driver-问题分析-有状态的服务-状态的处理

摘要: VH的driver对上层提供的接口,是会保持状态。这个状态,可以分为,查询的数据的状态,主要是为了提供翻页查询的功能。另一种状态,就是订阅。 有状态的服务: 状态是什么? 其实从调用方的角度更好的理解&#xff0c…

AIGC绘画设计——Stable Diffusion进阶使用

本文讲解,模型底模,VAE美化模型,Lora模型,hypernetwork。 文本Stable Diffusion 简称sd 欢迎关注留言,不定期追加更新! 使用模型 C站:https://civitai.com/ huggingface&#…

快团团大团长帮卖团长团长如何获得物流查询码?

一、功能说明 团长可自行生成物流查询码,直接将码发给顾客,顾客扫码可查询自己订单的物流状态! 用户扫码后,会出现用户在该团长处下单的所有快递订单。团员可查看该订单物流信息、进行退款申请,或直接联系团长。 二…

使用Python爬取华为市场游戏类APP应用

文章目录 1. 写在前面2. 接口分析3. 爬虫开发4. 下载链接获取 【🏠作者主页】:吴秋霖 【💼作者介绍】:擅长爬虫与JS加密逆向分析!Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守…

摘下戛纳大奖的《狗阵》,救得了华谊吗?

随着第77届戛纳国际电影节成功落幕,《狗阵》无疑成为了华语电影的最大赢家。 今年的戛纳电影节可以说是华语电影大年,《风流一代》《狗阵》《酱园弄》《九龙城寨之围城》等多部重量级影片亮相戛纳。 但最终抱得奖项而归的只有管虎导演的《狗阵》&#…

长虹55D3P海思平台固件破解

一 、背景 目前网上还没有长虹海思平台智能电视的固件打包解包教程,仅有一个znds的解包,但大佬迟迟没更新打包教程和工具。帖子中也没讲解解包的原理,对于不熟悉海思平台的来说,感觉无从下手。 znds海思解包贴:#长虹…

Vue 2.0使用Vue-count-to给数字添加增长动画

在开发后台管理系统时,时常会遇到数据汇总,为了页面展示更生动,用户体验更好,通常会对汇总的数字加一个逐步递增动画。 实现这个效果一般是用的 Vue-count-to这个插件,这是一款简单好用的一个数字滚动插件,…

3D视觉系统实现自动化上下料操作

在竞争激烈的汽车制造行业,提高生产效率、降低成本并保证产品质量是企业持续发展的关键。特别是在汽车制造过程中,各种零部件的上下料操作占据了大量的生产时间,因此如何实现这些操作的自动化、高效化成为了一个亟待解决的问题。 富唯智能3D视…

157.二叉树:二叉树的右视图(力扣)

代码解决 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* Tre…

【C++修行之道】类和对象(二)类的6个默认成员函数、构造函数、析构函数

目录 一、类的6个默认成员函数 二、构造函数 2.1 概念 2.2 特性 2.2.5 自动生成默认构造函数 不进行显示定义的隐患: 2.2.6 自动生成的构造函数意义何在? 两个栈实现一个队列 2.2.7 无参的构造函数和全缺省的构造函数都称为默认构造函数&#x…

pycharm 上一次编辑位置不见了

目录 pycharm2024版 上一次编辑位置不见了,研究发现移到了左下角了,如下图所示: 上一次编辑位置快捷键: pycharm2024版 上一次编辑位置不见了,研究发现移到了左下角了,如下图所示: 上一次编辑…

Minio篇:初识MinIO

1. MinIO快速入门 1.1.MinIO核心概念 下面介绍MinIO中的几个核心概念,这些概念在所有的对象存储服务中也都是通用的。 对象(Object) 对象是实际的数据单元,例如我们上传的一个图片。 存储桶(Bucket) 存储…

不同linux账户切换不同的cuda版本

原因 由于服务器中安装了两个版本的cuda(cuda10.1和cuda11.1),不同项目可能需要应用不同的cuda版本,但是自己又没有root权限或者只想在使用指定conda环境时改为用指定的cuda版本。总结起来有三种方法: 1、修改软链接指…

原生小程序一键获取手机号

1.效果图 2.代码index.wxml <!-- 获取手机号 利用手机号快速填写的功能&#xff0c;将button组件 open-type 的值设置为 getPhoneNumber--><button open-type"getPhoneNumber" bindgetphonenumber"getPhoneNumber">获取手机号</button> …

Javaweb基础之Cookie会话技术

大家好&#xff0c;这里是教授.F 引入&#xff1a; 我们想在登录一个网站时&#xff0c;能够显示我们上一次的登录时间啊&#xff0c;或者我们在该网站的浏览痕迹。哪这些要怎么做到&#xff1f;我们想&#xff0c;这些数据不可能从服务端给你返回来&#xff0c;因为一旦用户…

Line Worker(流水线工人休闲游戏模板)

您是地狱工厂的流水线工人。您的工作是在产品不断流动的情况下,将有缺陷的产品与合格产品区分开来。通过点击左右键来保留合格产品并丢弃不合格产品。错误太多,您将被解雇!《流水线工人》是一款有趣、轻松、超级休闲的游戏,适合所有年龄段的人! 亮点: - 上瘾的超休闲游戏…

Jvm(一)之栈、堆、方法区

前言-与正文无关 生活远不止眼前的苦劳与奔波&#xff0c;它还充满了无数值得我们去体验和珍惜的美好事物。在这个快节奏的世界中&#xff0c;我们往往容易陷入工作的漩涡&#xff0c;忘记了停下脚步&#xff0c;感受周围的世界。让我们一起提醒自己&#xff0c;要适时放慢脚步…

【JMeter接口自动化】第2讲 Jmeter目录结构

JMeter的目录结构如下&#xff1a; bin目录&#xff1a;可执行文件目录&#xff0c;启动jmeter时&#xff0c;就是启动bin目录下的ApacheJmeter.jar&#xff0c;jmeter.bat&#xff0c;jmeter.sh ApacheJmeter.jar:启动文件 jmeter.bat&#xff1a;Windows 的启动命令。 jmeter…