当前位置: 首页 > news >正文

《LINUX系统编程》笔记p8

信号集

由多个信号构成的一个数据集合(可以理解含有多个信号的数组)

信号集合的类型: sigset_t

操作信号集的函数

#include <signal.h>// 清空信号集内的全部信号,成功返回0,出错返回-1
int sigemptyset(sigset_t *set);// 设置(添加)全部信号到信号集内,成功返回0,出错返回-1
int sigfillset(sigset_t *set);// 添加某个信号signum到信号集,成功返回0,出错返回-1
int sigaddset(sigset_t *set, int signum);// 从信号集删除某个信号signum,成功返回0,出错返回-1
int sigdelset(sigset_t *set, int signum);// 判断某个信号signum是否在信号集 set 中。
// 在信号集中返回1, 不再返回0,出错返回-1。
int sigismember(const sigset_t *set, int signum);

信号屏蔽sigprocmask(2)

作用:设置屏蔽和解除屏蔽,当前代码段屏蔽信号集中的信号的中断。

#include <signal.h>/* Prototype for the glibc wrapper function */
成功返回0,出错返回-1,同时设置errno
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
// 参数: how: SIG_BLOCK 设置当前信号集阻塞信号。SIG_UNBLOCK 设置当前信号集从阻塞信号中删除。SIG_SETMASK 设置阻塞信号。
//  set 新的信号集
//  oldset 返回旧的信号集.

原子操作

示例:取银行存钱

步骤:

张三存钱
1. 银行确定钱数 x = 10000;
2. 查询你之前的钱数 money
3. 计算出最总的结果 result = money + x4. 修改这个结果。 money =  result。张三的女朋友给张三存钱
1. 银行确定钱数 x = 50;
2. 查询你之前的钱数 money
3. 计算出最总的结果 result = money + x
4. 修改这个结果。 money =  result。

sigprocmask 示例

#include <signal.h>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>void sig_handle(int sig) {printf("收到信号:%d\n", sig);
}void do_important_thing(void) {int ret;printf("开始做重要的事情\n");ret = sleep(10);if (ret != 0) printf("此事情被中断打断.\n");printf("结束做重要的事情\n");
}int main(int argc, char * argv[]) {sigset_t newset; // 新的信号集sigset_t oldset; // 用于保存之前的旧的信号集printf("PID:%d\n", getpid());signal(SIGINT, sig_handle);sigemptyset(&newset); // 清空 newset;sigaddset(&newset, SIGINT); // 将  SIGINT加入信号集合// 设置屏蔽newset中的信号,如果发生,则处于阻塞状态sigprocmask(SIG_BLOCK, &newset, &oldset);do_important_thing();// 解除阻塞,恢复之前的屏蔽状态。sigprocmask(SIG_SETMASK, &oldset, NULL);printf("做其他的事情\n");sleep(10);printf("程序退出\n");return 0;
}

sigsuspend 函数

作用:临时设置信号屏蔽字的原子操作。

函数格式

#include <signal.h>int sigsuspend(const sigset_t *mask);

示例

#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>void sig_handle(int sig) {printf("收到信号:%d\n", sig);
}void do_important_thing(void) {sigset_t temp_set;int ret;printf("开始做重要的事情\n");ret = sleep(5);if (ret != 0) printf("此事情被中断打断.\n");// 希望有信号就能够得到及时的响应。sigemptyset(&temp_set); // 清空sigsuspend(&temp_set); // 处理中断ret = sleep(5);if (ret != 0) printf("此事情被中断打断.\n");printf("结束做重要的事情\n");
}int main(int argc, char * argv[]) {sigset_t newset; // 新的信号集sigset_t oldset; // 用于保存之前的旧的信号集printf("PID:%d\n", getpid());signal(SIGINT, sig_handle);sigemptyset(&newset); // 清空 newset;sigaddset(&newset, SIGINT); // 将  SIGINT加入信号集合// 设置屏蔽newset中的信号,如果发生,则处于阻塞状态sigprocmask(SIG_BLOCK, &newset, &oldset);do_important_thing();// 解除阻塞,恢复之前的屏蔽状态。sigprocmask(SIG_SETMASK, &oldset, NULL);printf("做其他的事情\n");sleep(10);printf("程序退出\n");return 0;
}
abort 函数

abort函数

作用:让程序异常终止。

函数格式

#include <stdlib.h>void abort(void);

sigaction 函数

作用:代替signal 函数,让信号处理更可靠,并可以获取更多的信号信息,包括信号的发送进程ID等信息。

函数格式

#include <signal.h>
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

进程间通信(IPC)

IPC(Inter-Process Communitation)

进程间通信的进程关系可以是如下几种

  1. 父子进程
  2. 拥有相同父进程的两个子进程。
  3. 无亲缘关系的进程。

相关内容 《APUE》第十五章

UNIX 进程间通信的机制

  • 信号

  • 管道

    • 匿名管道(PIPE)
    • 有名管道(FIFO)
  • XSI IPC

    • 消息队列(Message Queue)
    • 信号量数组(semaphore Array)
    • 共享内存(Shared Memory)

管道

管道是Linux 内核中的一段内存,类似于循环队列,一个管道可以存储一段数据信息

创建管道的打开方式

int pipe(int fds[2]);
单工
| 进程1 |   ---->  | 进程2 |半双工(同一时刻只能一个方向传递数据)
| 进程1 |   -->--<-- | 进程2 |全双工
+ ---- +            +-------+
| 进程1 |   ----->   | 进程2 |
+ ---- +   <------- +-------+

管道的写操作 write(2)

  • write(fd[1]) 写管道的1端,写满会阻塞。

管道的读操作 read(2)

  • read(fd[0]) 读管道的0端,读空时会阻塞

管道容量

65536字节,默认是16个页(page),每个页4K。

管道发送的信号

管道读取端关闭,写管道会出发SIGPIPE信号。如果进程忽略此信号。则write(2) 返回-1并设置 errno为 EPIPE。

管道写端关闭,读取是read(2) 返回0.

示例代码

#include <time.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>void wait_child(int sig) {int status;pid_t pid;pid = wait(&status);printf("进程 pid: %d已经回收\n", pid);
}
void sig_handle(int sig) {printf("sig:%d\n", sig);
}int main(int argc, char * argv[]) {int fds[2];  // 用户存储管道打开的文件描述符int ret;char buf[1024];pid_t pid;signal(SIGPIPE, sig_handle);signal(SIGCHLD, wait_child);ret = pipe(fds); // 打开管道if (-1 == ret) {perror("pipe");return 1;}pid = fork();if (pid == -1) {perror("fork");return 2;}if (0 == pid) {close(fds[1]); // 关闭写端while(1) {ret = read(fds[0], buf, 1024);printf("ret:%d\n", ret);buf[ret] = 0;printf("buf:%s\n", buf);if (0 == strcmp(buf, "exit")) {close(fds[0]);return 0;}}}close(fds[0]); // 关闭读端while(1) {printf("请输入文字:");fflush(NULL); // 清空所有缓冲区。ret = read(0, buf, 1024); // "abc\n"buf[ret-1] = 0;write(fds[1], buf, ret-1);// if (0 == strcmp(buf, "exit")) {//     close(fds[1]);//     break;// }}printf("程序退出\n");return 0;
}
http://www.dtcms.com/a/363792.html

相关文章:

  • FPGA时序约束(四)--主时钟约束
  • ESLint 相关
  • 算法模板(Java版)_前缀和与差分
  • 2025大学生必考互联网行业证书排名​
  • Git 代码提交管理指南
  • 【鸿蒙面试题-6】LazyForEach 懒加载
  • 单多行文本溢出
  • 大数据毕业设计选题推荐-基于大数据的大学生就业因素数据分析系统-Spark-Hadoop-Bigdata
  • 从0到1掌握进度管理:核心概念解析+目标设定的新手友好指南!
  • Elasticsearch常用DSL快速查询指南
  • Linux一共有多少个版本?
  • 基于SpringBoot2+Vue2开发的储物柜管理系统
  • 详解STM32的完整启动流程
  • Java流程控制04——if选择结构(本文为个人学习笔记,内容整理自哔哩哔哩UP主【遇见狂神说】的公开课程。 > 所有知识点归属原作者,仅作非商业用途分享)
  • CentOS 7 服务器CPU突然飙升至100%?精准定位问题。
  • HBase Region
  • token存储方案
  • 告别传统照明!安科瑞 DALI 总线智能照明系统,解锁公建项目照明新体验
  • 机器人控制器开发(人形机器人产品设计)
  • 【C++模板】从起源到入门,小白必学泛型编程指南
  • 民间药方偏方网站整站源码 带数据PHP版
  • 【爬油管搜索视频软件】youtube爬虫工具,根据关键词采集搜到的视频数据
  • 分布式爬虫的全局请求间隔协调与IP轮换策略
  • 重磅!PS2021 和企业微信 5.0 可直接运行,统信兼容引擎 V3.3.2 全面升级!
  • 【最新Pr 2025安装包(Adobe Premiere Pro 2025 中文解锁版)安装包永久免费版下载安装教程】
  • 用了企业微信 AI 半年,这 5 个功能让我彻底告别重复劳动
  • 深度学习篇---DenseNet
  • 机器人控制器开发(整体架构2 Lerobot介绍)
  • [嵌入式embed][Qt]Qt5.12+Opencv4.x+Cmake4.x_测试Qt编译的opencv4.x的库
  • 移动硬盘删除东西后,没有释放空间