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 给覆盖。

最新文章

  1. Android 7.1 - App Shortcuts
  2. listener.ora增加监听端口
  3. 远程桌面Default.rdp 中各个参数的含义
  4. 【转】IOS设备旋转的内部处理流程以及一些【优化建议】
  5. FTP文件夹打开错误,Windows无法访问此文件夹
  6. Windows 8 IIS配置PHP运行环境
  7. SVN 分支及合并的介绍和实践---命令行
  8. C++ 牛人博客(不断更新中...)
  9. android 实现垂直的ProgressBar
  10. [ES6] Objects vs Maps
  11. SQL Server 数据库DML触发器 【一】
  12. 函数原型属性-JavaScript深入浅出(三)
  13. DeepLearning.ai学习笔记(一)神经网络和深度学习--Week4深层神经网络
  14. @RequestBody和@RequestParam区别
  15. swiper常见问题
  16. python中使用xlrd、xlwt和xlutils3操作Excel
  17. Python开发【项目】:学员管理系统(mysql)
  18. Linux Oracle安装
  19. Android NDK: Application targets deprecated ABI(s): armeabi Open File
  20. 【Oracle学习笔记-5--】集合操作之union,intersect和minus操作

热门文章

  1. [模板] 动态dp
  2. 牛客网Wannafly挑战赛25A 因子(数论 素因子分解)
  3. 使用Docker Swarm搭建分布式爬虫集群
  4. Arch Linux中安装Anaconda
  5. 洛谷P3185 分裂游戏
  6. bcftools或vcftools提取指定区段的vcf文件(extract specified position )
  7. unsigned 变量名:n
  8. shell脚本[] [[]] -n -z 的含义解析
  9. CodeForces7D 字符串hash + dp
  10. 图论分支-差分约束-SPFA系统