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

临淄网站设计深圳外贸soho网站建设

临淄网站设计,深圳外贸soho网站建设,做网站运营工资是不是很低,生鲜电商网站建设一、核心必掌握知识点(高频考点 实操重点)1. 信号递达与阻塞的深度理解(含内核态存储逻辑)关键概念区分概念定义核心差异信号未决(Pending)信号产生后到递达前的状态,进程已感知但未处理未决是…

一、核心必掌握知识点(高频考点 + 实操重点)

1. 信号递达与阻塞的深度理解(含内核态存储逻辑)

关键概念区分
概念定义核心差异
信号未决(Pending)信号产生后到递达前的状态,进程已感知但未处理未决是 “待处理” 状态,阻塞是 “禁止处理” 开关
信号阻塞(Block)进程主动设置 “屏蔽”,被阻塞信号即使产生也不会递达阻塞不影响信号产生(仍会标记未决),仅阻止递达
信号递达(Delivery)实际执行信号处理动作(默认 / 忽略 / 自定义)递达是最终处理环节,需先解除阻塞(若被阻塞)
内核中存储逻辑(必须理解)

进程 PCB(task_struct)中通过 3 个核心结构管理信号:

  • blocked(信号屏蔽字)sigset_t类型,位图结构,某 bit 为 1 表示对应信号被阻塞。
  • pending(未决信号集)sigset_t类型,位图结构,某 bit 为 1 表示对应信号已产生但未递达。
  • sighand(信号处理动作):存储每个信号的处理方式(SIG_DFL/SIG_IGN/ 自定义函数指针)。

示例场景:若进程阻塞SIGINT(2 号信号),此时按下Ctrl+C

  1. 内核标记pendingSIGINT的 bit 为 1(未决);
  2. blockedSIGINT的 bit 为 1(阻塞),信号不递达;
  3. 当进程解除SIGINT阻塞后,内核检测到未决信号,立即执行递达(如默认终止)。
实操练习:验证阻塞与未决
#include <iostream>
#include <unistd.h>
#include <signal.h>
using namespace std;// 打印未决信号集
void printPending() {sigset_t pending;sigpending(&pending); // 获取当前进程未决信号集cout << "Pending signals (31~1): ";for (int i = 31; i >= 1; i--) {if (sigismember(&pending, i)) cout << "1";else cout << "0";}cout << endl;
}int main() {sigset_t blockSet, oldSet;sigemptyset(&blockSet);       // 初始化空信号集sigaddset(&blockSet, SIGINT); // 将SIGINT(2号)加入阻塞集// 设置阻塞信号集,备份原阻塞集到oldSetsigprocmask(SIG_BLOCK, &blockSet, &oldSet);cout << "Block SIGINT, press Ctrl+C (5s later unblock)..." << endl;for (int i = 5; i > 0; i--) {printPending();sleep(1);}// 解除阻塞(恢复原阻塞集)sigprocmask(SIG_SETMASK, &oldSet, nullptr);cout << "Unblock SIGINT, now Ctrl+C will terminate process" << endl;while (1) sleep(1);return 0;
}

运行结果:按下Ctrl+C后,未决信号集第 2 位(SIGINT)会显示 “1”;5 秒后解除阻塞,进程立即被SIGINT终止。

2. 信号捕捉的完整流程(含内核态 / 用户态切换)

核心流程(必须能复述)
  1. 用户态执行主流程:进程在用户态运行main函数,此时发生中断 / 异常 / 系统调用,切换到内核态。
  2. 内核态检测信号:内核处理完中断 / 异常后,准备返回用户态前,检查进程的pendingblocked
    • 若存在未被阻塞的信号,且处理方式为 “自定义函数”,则不返回主流程,而是切换到用户态执行自定义处理函数。
  3. 用户态执行处理函数:处理函数执行完毕后,自动调用sigreturn系统调用,再次切换到内核态。
  4. 内核态恢复主流程:内核确认无新信号需递达,恢复主流程的上下文,切换回用户态继续执行main函数。
关键函数:sigaction(比signal更稳定,推荐使用)

signal函数存在兼容性问题,sigaction是 POSIX 标准接口,支持更精细的信号控制:

#include <signal.h>
// 函数原型
int sigaction(int signo, const struct sigaction *act, struct sigaction *oact);
  • struct sigaction核心字段
    • sa_handler:处理函数指针(SIG_DFL/SIG_IGN/ 自定义函数)。
    • sa_mask:执行处理函数期间,额外阻塞的信号集(防止处理函数被其他信号打断)。
    • sa_flags:控制信号行为(如SA_RESTART使被信号打断的系统调用自动重启)。
实操练习:用sigaction捕捉SIGINT
#include <iostream>
#include <unistd.h>
#include <signal.h>
using namespace std;void sigintHandler(int signo) {cout << "Catch SIGINT (signo=" << signo << "), wait 2s..." << endl;sleep(2); // 执行处理期间,若再次按Ctrl+C,因sa_mask会阻塞SIGINT,需等待处理完毕
}int main() {struct sigaction act, oldAct;// 初始化actact.sa_handler = sigintHandler;  // 设置自定义处理函数sigemptyset(&act.sa_mask);       // 初始化额外阻塞集sigaddset(&act.sa_mask, SIGINT); // 执行处理函数时,额外阻塞SIGINTact.sa_flags = 0;                // 默认行为// 设置SIGINT的处理动作,备份原动作到oldActsigaction(SIGINT, &act, &oldAct);cout << "Wait for SIGINT (press Ctrl+C), enter 'q' to quit" << endl;while (cin.get() != 'q');// 恢复SIGINT原处理动作sigaction(SIGINT, &oldAct, nullptr);return 0;
}

运行结果:第一次按Ctrl+C会执行处理函数(2 秒内再次按Ctrl+C无反应),处理完毕后恢复响应;输入q退出程序。

3. 可重入函数与竞态条件(避坑重点)

可重入函数定义
  • 可重入:多个控制流程(如主流程 + 信号处理函数)同时调用该函数,不会导致数据错乱(仅访问局部变量 / 参数,无全局 / 静态变量操作)。
  • 不可重入:调用后可能导致数据错乱,常见场景:
    1. 操作全局 / 静态变量(如全局链表插入);
    2. 调用malloc/free(堆管理用全局链表);
    3. 调用标准 I/O 函数(如printf,内部用全局缓冲区)。
竞态条件示例(不可重入函数问题)
#include <iostream>
#include <unistd.h>
#include <signal.h>
using namespace std;struct Node { int val; Node* next; } node1, node2, *head = nullptr;// 不可重入函数:操作全局链表head
void insert(Node* p) {p->next = head; // 步骤1:保存原head// 若此时发生信号,进入处理函数调用insert,会修改headsleep(1);       // 模拟信号打断head = p;       // 步骤2:更新head为p
}void sigHandler(int signo) {insert(&node2); // 信号处理函数调用insertcout << "Signal handler insert node2" << endl;
}int main() {node1.val = 1; node2.val = 2;signal(SIGINT, sigHandler); // 注册SIGINT处理函数insert(&node1); // 主流程调用insertcout << "Main insert node1" << endl;// 遍历链表(预期node1->node2,实际可能只有node2)Node* cur = head;while (cur) {cout << cur->val << " ";cur = cur->next;}return 0;
}

运行结果:主流程执行insert(&node1)sleep(1)时,按下Ctrl+C,信号处理函数插入node2并修改head;主流程恢复后继续执行head = &node1,最终链表仅node1(数据错乱)。

避坑方案
  1. 优先使用可重入函数(如自己实现无全局变量的工具函数);
  2. 若必须操作全局数据,在信号处理函数执行期间,通过sigprocmask阻塞相关信号(避免打断)。

4. SIGCHLD信号与僵尸进程处理(实战必备)

核心作用

子进程终止时,会向父进程发送SIGCHLD信号(默认处理动作是忽略),父进程可通过捕捉该信号,调用waitpid清理僵尸进程(避免轮询)。

关键特性
  • 子进程终止后若父进程未处理,会变为僵尸进程(Z状态);
  • 父进程若用sigactionSIGCHLD设为SIG_IGN,子进程终止后会自动清理(不产生僵尸进程,Linux 特有)。
实操练习:捕捉SIGCHLD清理僵尸进程
#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/types.h>
using namespace std;// SIGCHLD处理函数:清理所有终止的子进程
void sigchldHandler(int signo) {pid_t id;// WNOHANG:非阻塞,有子进程终止则返回其PID,否则返回0while ((id = waitpid(-1, nullptr, WNOHANG)) > 0) {cout << "Clean zombie child, PID=" << id << endl;}
}int main() {// 注册SIGCHLD处理函数struct sigaction act;act.sa_handler = sigchldHandler;sigemptyset(&act.sa_mask);act.sa_flags = 0;sigaction(SIGCHLD, &act, nullptr);// 创建3个子进程for (int i = 0; i < 3; i++) {pid_t cpid = fork();if (cpid == 0) {cout << "Child PID=" << getpid() << ", exit after 2s" << endl;sleep(2);exit(0); // 子进程终止,发送SIGCHLD}}// 父进程持续运行,等待子进程终止while (1) sleep(1);return 0;
}

运行结果:3 个子进程 2 秒后陆续终止,父进程通过SIGCHLD处理函数自动清理,无僵尸进程残留(可通过ps aux | grep 程序名验证)。

二、重要理解类知识点(原理性内容)

1. 内核态与用户态的切换(信号处理的底层支撑)

核心区别
维度用户态(Ring 3)内核态(Ring 0)
权限仅能访问用户空间(0~3GB),无硬件操作权限可访问内核空间(3~4GB),有所有硬件操作权限
执行代码应用程序代码(如main函数)内核代码(如系统调用、中断处理)
切换触发系统调用(如fork)、异常(如除零)、中断(如键盘)处理完毕后自动切换回用户态
与信号处理的关联

信号处理函数在用户态执行,但信号的检测、未决 / 阻塞标记的维护在内核态完成:

  • 当内核检测到可递达信号时,会 “跳转” 到用户态执行处理函数;
  • 处理函数返回后,通过sigreturn系统调用切回内核态,再恢复主流程。

2. volatile关键字(解决编译器优化导致的 bug)

作用

告知编译器:被修饰的变量不允许优化,每次访问必须从内存读取(而非寄存器缓存),保证内存可见性。

典型场景

信号处理函数修改全局变量,主流程循环判断该变量(无volatile会导致优化 bug):

#include <iostream>
#include <unistd.h>
#include <signal.h>
using namespace std;// 必须加volatile,否则编译器可能将flag缓存到寄存器
volatile int flag = 0;void sigHandler(int signo) {flag = 1;cout << "Signal set flag=1" << endl;
}int main() {signal(SIGINT, sigHandler);cout << "Wait for SIGINT (press Ctrl+C)" << endl;// 若flag无volatile,编译器可能优化为while(1)(认为flag不会变)while (!flag);cout << "Main exit (flag=1)" << endl;return 0;
}

注意:编译时加-O2(优化选项),若不加volatile,程序按下Ctrl+C后仍会卡在while循环;加volatile则正常退出。

三、了解类知识点(扩展认知)

1. 实时信号与常规信号(编号差异)

  • 常规信号:编号 1~31,不支持排队(同一信号多次产生,递达时仅处理 1 次);
  • 实时信号:编号 34~64,支持排队(多次产生会依次递达),用于需要精确处理的场景(如工业控制),本章暂不涉及。

2. Core Dump(核心转储)

  • 作用:进程异常终止时(如SIGSEGV段错误),将用户空间内存数据保存到core文件,用于事后调试(gdb ./程序名 core.进程号)。
  • 开启方法:默认关闭,通过ulimit -c 1024(允许最大 1024KB 的 core 文件)开启,测试代码:
    #include <stdio.h>
    int main() {int* p = nullptr;*p = 100; // 非法内存访问,产生SIGSEGV,触发Core Dumpreturn 0;
    }

    编译运行后会生成core.xxx文件,用gdb ./a.out core.xxx可定位到错误行。

3. 操作系统的中断驱动模型

  • 操作系统通过 “中断”(硬件中断如键盘、软中断如系统调用)驱动运行,核心是 “中断向量表(IDT)”:
    • 每个中断对应一个处理例程(如0x20是时钟中断,0x80是系统调用);
    • 时钟中断定期触发,推动进程调度(如时间片轮转),是操作系统的 “心脏”。

http://www.dtcms.com/a/468620.html

相关文章:

  • 百度关键词模拟点击软件重庆网站排名优化
  • 在那个网站找模具做网站运营专员做什么
  • 先做网站后备案吗网站怎么免费建站
  • 企业seo推广没内容的网站怎么优化
  • 网站空间怎么备份seo内部优化
  • 广州外贸营销型网站建设怎么做一个购物平台网站
  • 电子商务网站建设实训内容设计网站推荐 zoo
  • c 网站开发 简单例子镇江微信推广平台
  • 网页编成网站沙坪坝网站建设公司选哪家好
  • 部分网站dns解析失败wordpress 后台制作
  • 小程序做视频网站wordpress中文下载方法
  • 西塞山区建设局网站重点专业建设网站 建设方案
  • 情侣博客网站模板下载合肥房产网58同城
  • 微网站开发语言专门做教育的视频网站
  • 塑胶 东莞网站建设网站要怎么做
  • 免费发广告的网站大全qq官方网站
  • 企业网站管理系统设置91人才网赣州招聘网
  • 用人名做网站域名crm系统网址
  • 开不锈钢公司怎么做网站健康陕西app管理端最新版
  • 广东中国移动网站wordpress 封ip段
  • 十大金融公司排名廊坊网站快速排名优化
  • 网站建设方案书 阿里云网站页面优化签象客
  • 江苏百城建设有限公司官方网站上海做网站建设的公司排名
  • 邢台做网站建设公司哪家好?wordpress可爱的主题
  • 网上有做logo的网站吗为什么没人做物流网站
  • 北京网站建设哪里好网站开发的解决方案
  • 网站设计培训班老师西安景观设计公司排行
  • 网站建设的公司这个中国建设银行网站荆门网点查询系统
  • 新媒体营销有哪些岗位成都关键词优化
  • 一条龙搭建网站三屏营销型网站建设