OS57.【Linux】理解信号: 信号的产生(2) 键盘输入和系统调用

OS57.【Linux】理解信号: 信号的产生(2) 键盘输入和系统调用

目录

1.知识回顾

2.Ctrl+C是如何变成信号的

硬件中断

信号

变成信号的整个过程

回显的含义

3.信号产生是异步的

4.信号的产生: 使用系统调用

kill

编写"kill -signo pid"命令

raise

abort


1.知识回顾

之前在OS57.【Linux】理解信号: 信号的产生(1)文章讲过:Ctrl+C可以杀死前台进程,下面讲讲Ctrl+C是如何变成信号的

2.Ctrl+C是如何变成信号的

硬件中断

操作系统为了保证安全,进程是无法直接读取键盘数据的,显然键盘的键位被按下,一定是操作系统先知道,由于Linux的"一切皆文件"的思想,键盘也是文件,那么操作系统肯定会先读取键盘缓冲区文件

那操作系统怎么知道键盘上有数据要读取呢?

答: CPU上的针脚和外设是间接相连的,键盘有数据时会向CPU发送硬件中断,有CPU告诉操作系统将键盘数据拷贝到键盘文件缓冲区

计算机中的外设有很多,显然每个外设都可以向CPU发送中断,那如何确保是键盘发送的中断呢?

答: 每个中断都有唯一的编号,这个编号为中断号,CPU依此来区分不同的中断

外设向CPU发送中断,CPU根据中断解释出中断号,保护模式下, CPU根据中断号到中断描述符表找出对应中断例程的地址,然后CPU跳转到那里执行,结束后CPU通过iret返回

这个中断例程可以是操作系统将键盘外设上的数据拷贝到键盘文件缓冲区

补充: 如果多个硬件同时发送中断,操作系统会串行处理

信号

上方讲的是硬件中断,之前在OS57.【Linux】理解信号: 信号的产生(1)文章讲的信号是用软件的方式模拟硬件中断

变成信号的整个过程

用户按下Ctrl+C,这个键盘输入产生一个硬件中断,被操作系统获取,解释成信号,发送给目标前台进程, 前台进程因为收到信号,进而引起进程退出

回显的含义

正常情况下,从键盘输入的数据会显示到显示器上,这是因为操作系统将键盘缓冲区的数据拷贝到显示器的缓冲区

注: 图中的"键盘文件"和"显示器文件"是根据Linux的"一切皆文件"的思想,将硬件的内容抽象为文件

得出不回显的含义: 键盘缓冲区的数据不拷贝到显示器的缓冲区

3.信号产生是异步的

前台进程在运行过程中用户随时可能按下Ctrl+C而产生一个信号,也就是说该进程的用户空间代码执行到任何地方都有可能收到SIGINT信号而终止,所以信号相对于进程的控制流程来说是异步
(Asynchronous)的

1.例子理解: 操作系统不知道用户什么时候会按键盘,这是异步的

2.对立面理解: 同步的反义词是异步

信号是进程之间事件异步通知的一种方式,属于软中断,软中断是仿照硬件中断实现的软件逻辑

4.信号的产生: 使用系统调用

新建以下文件:

test_signal ├── hello_world.cpp ├── makefile └── test_signal.cpp

hello_world.cpp写入:

makefile:

kill

作用: 向指定进程发送指定的信号

kill的参数:

pid: 进程号

sig: 信号编号

编写"kill -signo pid"命令

test_signal.cpp写入:

#include <unistd.h> #include <iostream> #include <signal.h> int main(int argc,char* argv[]) { if (argc!=3) { std::cout<<"用法: kill -signo pid"<<std::endl; exit(1); } std::string signo_s=argv[1]; std::string pid_s=argv[2]; int signo=std::stoi(std::string(signo_s,1)); int pid=stoi(pid_s); if (pdi<0||pid>64) { std::cout<<"非法的信号编号"<<std::endl; exit(2); } if (kill(pid,signo)) { perror("kill failed"); exit(3); } std::cout<<"已发送信号"<<std::endl; return 0; }

启动一个无限打印Hello World的进程,尝试杀死

运行结果:

raise

作用: 发送一个信号给调用者

sig是信号的编号

test_signal.cpp写入:

#include <unistd.h> #include <iostream> #include <signal.h> int main(int argc,char* argv[]) { int cnt=0; for(;;) { std::cout<<"Hello World!"<<std::endl; sleep(1); cnt++; if (cnt==5) raise(9); } return 0; }

运行结果:

结论: kill(getpid(),signo)和rasie(signo)作用等价

abort

作用: 给调用者发送6号信号SIGABRT

可以手动捕获abort()发送的6号信号,test_signal.cpp写入:

#include <unistd.h> #include <iostream> #include <signal.h> void myhandler(int signo) { std::cout<<"已执行自定义动作,信号编号为"<<signo<<"号"<<std::endl; } int main(int argc,char* argv[]) { signal(SIGABRT,myhandler); int cnt=0; for(;;) { std::cout<<"Hello World!"<<std::endl; sleep(1); cnt++; if (cnt==5) abort(); } return 0; }

运行结果:

发现捕获SIGABRT信号后,程序仍然终止了

abort函数发送SIGABRT信号,编号为6

结论: abort()除了能发送信号,内部实现有终止进程这个功能

Read more

深入理解 Linux 基础 IO:从 C 库到系统调用的完整剖析

深入理解 Linux 基础 IO:从 C 库到系统调用的完整剖析

🔥个人主页:Cx330🌸 ❄️个人专栏:《C语言》《LeetCode刷题集》《数据结构-初阶》《C++知识分享》 《优选算法指南-必刷经典100题》《Linux操作系统》:从入门到入魔 《Git深度解析》:版本管理实战全解 🌟心向往之行必能至 🎥Cx330🌸的简介: 目录 前言: 一、理解 “文件” 二、温故知新:C 标准库的文件 IO 操作  2.1 C语言文件操作常用函数 2.2 文件写入:fwrite(附加其他函数) 2.3 文件读取:fread(附加其他函数) 2.4 标准输入输出:stdin、stdout、stderr 三、走进内核:文件相关的系统调用接口 3.

By Ne0inhk
Flutter for OpenHarmony 实战:Injectable — 自动化依赖注入大师

Flutter for OpenHarmony 实战:Injectable — 自动化依赖注入大师

Flutter for OpenHarmony 实战:Injectable — 自动化依赖注入大师 前言 在维护 Flutter for OpenHarmony 商业级项目时,由于功能重叠与模块解耦的需求,代码库中会充斥着大量的 Service(业务服务)、Repository(数据中心)及 Bloc/ViewModel。如果采用手动实例化这些类并逐层透传,代码会迅速演变成不可维护的“意大利面条”。 依赖注入 (Dependency Injection, DI) 是解决该问题的业界公认方案。而 Injectable 配合 GetIt,则是 Dart 生态中实现 DI 的皇冠。它能通过极其简洁的注解,在编译期自动生成复杂的注册代码。本文将带你探索如何利用 Injectable 构建一个灵活适配鸿蒙多运行环境的高级架构。 一、为什么 Injectable 是鸿蒙项目的必选项? 1.1 依赖管理的解耦

By Ne0inhk
Flutter for OpenHarmony 实战:FFIGEN — 自动化打通鸿蒙 C 语言接口

Flutter for OpenHarmony 实战:FFIGEN — 自动化打通鸿蒙 C 语言接口

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net 前言 在 Flutter for OpenHarmony 开发中,当我们需要调用鸿蒙系统提供的原生 C/C++ 能力(如:高性能图像处理、系统级的硬件通信、或者是复用现有的 C 语言算法库)时,dart:ffi 是必经之路。 然而,手动编写 C 语言结构体(struct)和函数指针的 Dart 映射代码不仅枯燥无味,还极度容易因为一个字节偏移的错误导致鸿蒙应用直接崩溃(Segment Fault)。ffigen 是 Dart 官方提供的终极工具,它可以通过解析 C 语言头文件(.h),全自动生成安全、高性能的 Dart 胶水代码。本文将教你如何自动化驱动鸿蒙应用的底层性能。 一、

By Ne0inhk
Flutter 组件 flutterw_sidekick_plugin 适配鸿蒙 HarmonyOS 实战:侧翼脚手架扩展,构建工程自动化与环境一致性治理架构

Flutter 组件 flutterw_sidekick_plugin 适配鸿蒙 HarmonyOS 实战:侧翼脚手架扩展,构建工程自动化与环境一致性治理架构

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 组件 flutterw_sidekick_plugin 适配鸿蒙 HarmonyOS 实战:侧翼脚手架扩展,构建工程自动化与环境一致性治理架构 前言 在鸿蒙(OpenHarmony)生态迈向大规模团队协作、涉及多分支并行开发及复杂的 SDK 版本管控的背景下,如何确保每一位开发者的本地构建环境(Flutter/Dart SDK)与生产基准完全对齐,已成为保障项目交付质量的“工程定海神针”。在鸿蒙设备这类强调定制化编译工具链与私有插件依赖的环境下,如果团队缺乏统一的脚手架工具,由于由于本地 SDK 版本的微小代差(如空安全检测差异),极易由于由于“环境不一致”导致代码在不同机器上产生不可预知的编译崩溃。 我们需要一种能够深度集成 Sidekick、支持自定义命令扩展且具备“强制版本锁死”能力的脚手架治理方案。 flutterw_sidekick_plugin 为 Flutter 开发者引入了基于 Sidekick

By Ne0inhk