三十三、Linux 进程与信号——中断系统调用和函数可重入性
33.1 中断系统调用
- 进程调用 “慢” 系统调用时,如果发生了信号,内核会重启系统调用。
- 慢系统调用
- 可能会永久阻塞的系统调用
- 从终端设备、管道或网络设备上的文件读取
- 向上述文件写入
- 某些设备上的文件打开
- pause 和 wait 系统调用
- 一些设备的 ioctl 操作
- 一些进程间通信函数
33.1.1 慢系统调用引起的调用重启
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h> void sig_handler(int signo)
{
if(signo == SIGTSTP){
printf("SIGTSTP occured\n");
}
} int main(void)
{
char buffer[];
ssize_t size; if(signal(SIGTSTP, sig_handler) == SIG_ERR){
perror("signal sigtstp error");
} printf("begin running and waiting for signal\n");
size = read(STDIN_FILENO, buffer, );
if(size < ){
perror("read error");
} printf("reading finished\n"); if(write(STDOUT_FILENO, buffer, size) != size) {
perror("write error");
}
printf("end running\n");
return ;
}

33.1.2 自定义函数
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h> void sig_handler(int signo)
{
if(signo == SIGTSTP){
printf("SIGTSTP occured\n");
}
} void call_fun(void)
{
printf("begin running call_fun\n");
sleep();
printf("end running call_fun\n");
} int main()
{
if(signal(SIGTSTP, sig_handler) == SIG_ERR){
perror("signal sigtstp error");
} printf("begin running main\n");
call_fun();
printf("end running main\n");
}

33.2 函数可重入性
- 在调用某个函数过程中出现信号,且该信号处理函数中再次调用该函数
- 访问全局或静态变量的函数是不可重入函数
- 即前后数据不一致
- 若是函数内部的局部变量,则此函数是可重入函数
- 即前后数据一致
- 访问全局或静态变量的函数是不可重入函数
- 程序片段如下:

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> int g_v[];
int *h_v; ///< 堆中变量 void set(int val)
{
int a_v[]; int i = ;
for(; i < ; i++) {
a_v[i] = val;
g_v[i] = val;
h_v[i] = val;
sleep();
} printf("g_v:");
for(i = ; i < ; i++){
if(i != ) {
printf(", %d", g_v[i]);
}
else {
printf(", %d", g_v[i]);
}
}
printf("\n"); printf("h_v:");
for(i = ; i < ; i++){
if(i != ) {
printf(", %d", h_v[i]);
}
else {
printf(", %d", h_v[i]);
}
} printf("\n");
printf("a_v:");
for(i = ; i < ; i++){
if(i != ) {
printf(", %d", a_v[i]);
}
else {
printf(", %d", a_v[i]);
}
}
} void sig_handler(int signo)
{
if(signo == SIGTSTP){
printf("SIGTSTP occured\n");
set();
printf("\nend SIGTSTP\n");
}
}
int main(void)
{
if(signal(SIGTSTP, sig_handler) == SIG_ERR){
perror("signal sigtstp error");
} h_v = (int *)calloc(, sizeof(int)); printf("begin running main\n");
set();
printf("\nend running main\n");
return ;
}
运行结果:

全局变量中的数据不可控,局部变量都为 10
第一次调用 set 函数的时候,set(10) 中的循环运行了 2 次,此时 i = 2,然后中断,再次运行set(20) 函数,此时将所有变量中的值覆盖掉了,中断完了之后,函数继续从中断的地方运行,此时中断的地方 i = 2,则全局变量和堆变量从此处开始运行,后面的 20 都被 10 给覆盖。
三十三、Linux 进程与信号——中断系统调用和函数可重入性的更多相关文章
- 三十四、Linux 进程与信号——信号特点、信号集和信号屏蔽函数
34.1 信号特点 信号的发生是随机的,但信号在何种条件下发生是可预测的 进程杠开始启动时,所有信号的处理方式要么默认,要么忽略:忽略是 SIGUSR1 和 SIGUSR2 两个信号,其他都采取默认方 ...
- 函数可重入问题reentrant functions(函数执行过程中可以被中断,允许多个副本)
最近经常听到这个名词,以前也听到过,不过接触更多的是“线程安全问题”,而且本人也一直理解的是两个名字的含义是一样的.今天仔细总结一下这个名词相关的概念. 引用博文:可重入函数和不可重入函数 (http ...
- 三十、Linux 进程与信号——信号的概念及 signal 函数
30.1 信号的基本概念 信号(signal)机制是Linux 系统中最为古老的进程之间的通信机制,解决进程在正常运行过程中被中断的问题,导致进程的处理流程会发生变化 信号是软件中断 信号是异步事件 ...
- 二十三、Linux 进程与信号---进程链和进程扇、守护进程和孤儿进程以及僵尸进程
23.1 进程链和进程扇 23.1.1 概念 进程链:一个父进程构建出一个子进程,子进程再构建出子子进程,子子进程构建出子子子进程.... 这种就为进程链 进程扇:一个父进程构建出多个子进程,子进程都 ...
- 三十一、Linux 进程与信号——SIGCHLD 信号、kill和raise函数以及alarm函数
31.1 SIGCHLD 信号 子进程状态发生变化(子进程结束)产生该信号,父进程需要使用 wait 调用来等待子进程结束并回收它. 避免僵尸进程 #include <stdio.h> # ...
- 第9章 Linux进程和信号超详细分析
9.1 进程简单说明 进程是一个非常复杂的概念,涉及的内容也非常非常多.在这一小节所列出内容,已经是我极度简化后的内容了,应该尽可能都理解下来,我觉得这些理论比如何使用命令来查看状态更重要,而且不明白 ...
- 十八、Linux 进程与信号---进程介绍
18.1 进程的概念 程序:程序(program)是存放再磁盘文件中的可执行文件 进程 程序的执行实例被称为进程(process) 一个程序的执行实例可能由多个 进程具有独立的权限和职责.如果系统中某 ...
- Linux 进程与信号的概念和操作
进程 主要参考: http://www.bogotobogo.com/Linux/linux_process_and_signals.php 信号与进程几乎控制了操作系统的每个任务. 在shell中输 ...
- Linux 进程与信号的概念和操作 linux process and signals
进程 主要参考: http://www.bogotobogo.com/Linux/linux_process_and_signals.php 译者:李秋豪 信号与进程几乎控制了操作系统的每个任务. 在 ...
随机推荐
- TCP/UDP区别
一:1. 大体上来说,TCP和UDP都是通过Internet发送数据包的协议.都建立在Internet协议上.就是无论你是用TCP协议还是用UDP协议发送数据包,都会被发送到IP地址: 2.数据包的处 ...
- QML学习笔记(五)— 做一个简单的待做事项列表
做一个简单的QML待做事项列表,能够动态添加和删除和编辑数据 GitHub:八至 作者:狐狸家的鱼 本文链接:QML学习笔记(五)— 做一个待做事项列表 主要用到QML:ListView 效果 全部代 ...
- 使用jquery.pjax实现SPA单页面应用
前面文章介绍了前端路由简单实现和Pjax入门方面的文章,今天来分享一个单页面应用神器jquery.pjax.js. HTML 我们准备一个加载div#loading,默认隐藏,ajax请求的时候才显示 ...
- 第三十一篇-TextInputLayout(增强文本输入)的使用
效果图: 密码使用的是增强文本输入类型,当密码长度小于6或者密码长度大于10的时候就会给出提示. main.xml 当添加TextInputLayout时,旁边会有一个下载符号,如果点不动,可以右键点 ...
- 第二十二篇-Guideline基准线
效果图: 前5个是button填充的,最后一个是线性布局下放置一个button在填充. layout.xml <?xml version="1.0" encoding=&qu ...
- pycharm 出现 "PEP:8 expected 2 blank lines ,found 0"
https://blog.csdn.net/modangtian/article/details/79687623 这句话的意思是“有两个空白行,但是没有发现.” 在声明函数的那一行的上方必须有两行的 ...
- pytest 8 参数化parametrize
pytest.mark.parametrize装饰器可以实现用例参数化 1.以下是一个实现检查一定的输入和期望输出测试功能的典型例子 import pytest @pytest.mark.parame ...
- 4.1、实现4个LED灯同时闪烁
图中可以看出,P1的0.1.3.4引脚分别连接着4个LED.控制引脚状态,来控制LED. #include "ioCC2530.h" //引用CC2530头文件 /******** ...
- C#梳理【集合Collection】
C# 集合(Collection) 集合(Collection)类是专门用于数据存储和检索的类.这些类提供了对栈(stack).队列(queue).列表(list)和哈希表(hash table)的支 ...
- 关于串session
关于session: 最近在用IE浏览器调试不同用户所拥有的权限功能,出现了串session.串session,主要的流程结构如下: 解决方法: 在IE快捷方式上点击鼠标右键>属性>快捷方 ...