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 进程与信号——中断系统调用和函数可重入性的更多相关文章

  1. 三十四、Linux 进程与信号——信号特点、信号集和信号屏蔽函数

    34.1 信号特点 信号的发生是随机的,但信号在何种条件下发生是可预测的 进程杠开始启动时,所有信号的处理方式要么默认,要么忽略:忽略是 SIGUSR1 和 SIGUSR2 两个信号,其他都采取默认方 ...

  2. 函数可重入问题reentrant functions(函数执行过程中可以被中断,允许多个副本)

    最近经常听到这个名词,以前也听到过,不过接触更多的是“线程安全问题”,而且本人也一直理解的是两个名字的含义是一样的.今天仔细总结一下这个名词相关的概念. 引用博文:可重入函数和不可重入函数 (http ...

  3. 三十、Linux 进程与信号——信号的概念及 signal 函数

    30.1 信号的基本概念 信号(signal)机制是Linux 系统中最为古老的进程之间的通信机制,解决进程在正常运行过程中被中断的问题,导致进程的处理流程会发生变化 信号是软件中断 信号是异步事件 ...

  4. 二十三、Linux 进程与信号---进程链和进程扇、守护进程和孤儿进程以及僵尸进程

    23.1 进程链和进程扇 23.1.1 概念 进程链:一个父进程构建出一个子进程,子进程再构建出子子进程,子子进程构建出子子子进程.... 这种就为进程链 进程扇:一个父进程构建出多个子进程,子进程都 ...

  5. 三十一、Linux 进程与信号——SIGCHLD 信号、kill和raise函数以及alarm函数

    31.1 SIGCHLD 信号 子进程状态发生变化(子进程结束)产生该信号,父进程需要使用 wait 调用来等待子进程结束并回收它. 避免僵尸进程 #include <stdio.h> # ...

  6. 第9章 Linux进程和信号超详细分析

    9.1 进程简单说明 进程是一个非常复杂的概念,涉及的内容也非常非常多.在这一小节所列出内容,已经是我极度简化后的内容了,应该尽可能都理解下来,我觉得这些理论比如何使用命令来查看状态更重要,而且不明白 ...

  7. 十八、Linux 进程与信号---进程介绍

    18.1 进程的概念 程序:程序(program)是存放再磁盘文件中的可执行文件 进程 程序的执行实例被称为进程(process) 一个程序的执行实例可能由多个 进程具有独立的权限和职责.如果系统中某 ...

  8. Linux 进程与信号的概念和操作

    进程 主要参考: http://www.bogotobogo.com/Linux/linux_process_and_signals.php 信号与进程几乎控制了操作系统的每个任务. 在shell中输 ...

  9. Linux 进程与信号的概念和操作 linux process and signals

    进程 主要参考: http://www.bogotobogo.com/Linux/linux_process_and_signals.php 译者:李秋豪 信号与进程几乎控制了操作系统的每个任务. 在 ...

随机推荐

  1. iptables(2)

    MASQUERADE同样是做源地址转换,只不过防火墙会根据该策略自动查找可用的公网IP地址,适应变化的情况•若接口使用ppp+,表示匹配ppp0.ppp1……中任意可用的拨号连接•若需要演示操作,可以 ...

  2. C/C++ 控制台窗口暂停

    为什么我看不到控制台的输出结果? 在编写C++程序中,经常会出现,控制台窗口一闪就消失了的情况 为什么会这样? 原因简单到有点可笑:因为程序运行结束了 对于控制台程序,操作系统让它开始运行前会为它造一 ...

  3. 编写高质量代码:改善Java程序的151个建议 --[98~105]

    建议的采用顺序是List中泛型顺序依次为T.?.Object (1).List是确定的某一个类型 List表示的是List集合中的元素都为T类型,具体类型在运行期决定:List<?>表示的 ...

  4. Spring Boot 日志配置方法(超详细)

    默认日志 Logback : 默认情况下,Spring Boot会用Logback来记录日志,并用INFO级别输出到控制台.在运行应用程序和其他例子时,你应该已经看到很多INFO级别的日志了. 从上图 ...

  5. 洛谷P1041 传染病控制

    解:搜索...... 我们可以每次选择分支少的搜索,或者说,贪心的搜索当前更优的决策. 每一层把能剪的点搞出来,按照度数/SIZ排序,然后依次搜索.加个最优化剪枝就完事了. #include < ...

  6. IO 流读取文件时候出现乱码 文件编码格式问题 怎么转换解决方法

    在使用下面这个写法时候UTF-8文件编码 在读取时候出现乱码问题. File myFile=new File("文件路径"); BufferedReader in = new Bu ...

  7. 模块---hashlib、configparse、logging

    一.hashlib模块 hashlib模块介绍:hashlib这个模块提供了摘要算法,例如 MD5.hsa1 摘要算法又称为哈希算法,它是通过一个函数,把任意长度的数据转换为一个长度固定的数据串,这个 ...

  8. Filter(过滤器)

    一.Filter过滤器(重要) Javaweb中的过滤器可以拦截所有访问web资源的请求或响应操作. 1.Filter快速入门 1.1.步骤: 1. 创建一个类实现Filter接口 2. 重写接口中方 ...

  9. IDEA或Webstorm设置Ctrl+滚轮调整字体大小

    按Ctrl+Shift+A,出现搜索框 输入mouse: 点击打开这个设置:勾选 点击ok,之后就可以通过Ctrl+滚轮 调整字体大小了.

  10. Tree Restoration Gym - 101755F (并查集)

    There is a tree of n vertices. For each vertex a list of all its successors is known (not only direc ...