基础知识之操作系统实验(四)-信号机制

实验概述

信号的定义

  • 信号是进程在运行过程中,由自身产生或由进程外部发过来的消息(事件)。
  • 信号是硬件中断的软件模拟(软中断)。

每一个信号用一个整形常量宏表示,以SIG开头,在头文件<signal.h>中定义
本实验需要使用两个特殊的系统调用 kill()和signal()

1.kill函数

作用:用于发送指定类型的信号,即信号发送函数

头文件: #include <signal.h> #include <sys/types.h>

语法格式 : int kill (pid,sig)

参数解读 :
int pid (接受信号的进程号),
int sig(要发送的信号)
其中 pid > 0 表示要将信号发送给那个进程
Pid=0 表示要将信号发送给当前进程所属的进程组里的所有进程
其他值省略

返回值 发送成功返回0,失败返回 -1

2. signal函数

作用 用来通知内核如何处理某个特定的信号

头文件 #include <signal.h>

语法格式 signal(sig, handler)

参数解读
int sig(要捕捉的信号类型,sig为0表示没有收到任何信号,其它值得含义见下表),
void ( * handler)(int) handler 是函数指针,表示要对该信号进行捕捉的函数,其取值有三种,
SIG_IGN表示进程在运行中收到特定信号后,忽略它,不做任何处理。
SIG_DFL表示交由系统默认处理
FUNC表示收到信号后转去执行用户指定的一个函数

3.信号

每一个信号用一个整形常量宏表示,以SIG开头,在头文件<signal.h>中定义
本实验需要使用两个特殊的系统调用 kill()和signal()
Linux内核定义的常用信号
值 名字 说明
01 SIGHUP 挂起
02 SIGINT 用户按CTRL+C中断
03 SIGQUIT 退出 用户按CTRL+
04 SIGILL 非法指令
05 SIGTRAP 跟踪陷阱
06 SIGIOT 执行i/0时硬件错误
07 SIGBUS 总线错误
08 SIGFPE 浮点运算错误
09 SIGKILL 终止进程(不可屏蔽)
10 SIGUSR1用户自定义信号1
11 SIGSEGV内存非法访问
12 SIGUSR2用户自定义信号2
13 SIGPIPE 向非法管道写入
14 SIGALRM定时报警
15 SIGTERM kill系统调用
17 SIGCHLD 终止子进程
19 SIGSTOP 进程暂停
30 SIGPWR 电影故障

实验1

要求:编写代码实现在键盘上输入CTRL+C产生的SIGINT信号

#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

int main()
{
  int p1,p2,i;
  p1=fork();
  if(p1==0)
  {	
    lockf(1,1,0);
    for(i=0;i<5;i++)
    {	
      printf("child1=%d\n",i);
      sleep(2);
    }
    lockf(1,0,0);
  }
  else
  {	
   p2=fork();
   if(p2==0) 
  {
   lockf(1,1,0);
  
   for(i=0;i<5;i++)
   {	
     printf("child2=%d\n",i);
     sleep(2);
   }
   lockf(1,0,0);
  }
  else
  {
    lockf(1,1,0);
    for(i=0;i<5;i++)
    {	
     printf("parent=%d\n",i);
     sleep(2);
    }
     lockf(1,0,0);
     wait(0);
     wait(0);
     printf("互斥使用监视器成功\n");		
    }
  }
     return 0;
}

运行结果:
在这里插入图片描述编译运行后,是个死循环,如果没有Signal(SIGINT,SIG_IGN)这句话,可以按CTRL+C退出,现在只能按CRTL+\ 退出

实验2

实验要求
编写源代码实现当从键盘输入的首字母为a时,程序将通过SIGQUIT把自己终止

#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
Void main()
{
  char in[10]=”hello”;
  while(1)
   {
     printf("请任意输入一个长度小于10的字符串,并回车。如果想退出请确保首字母为 a");
     Scanf("%s",in);
     if(in[0]=='a')
       {
        printf(“本程序马上启动自杀程序\n”);
        kill(getpid(),SIGQUIT);获取当前进程的ID号    SIGQUIT  退出 用户按CTRL+\
  
       }
   }
}

实验结果
在这里插入图片描述

实验3

运行并分析程序结果

#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int i;
void intfun()  
{
   i=0;
}
void main()
{
   int k,j,pid;
   j=1;

while((pid=fork())==-1);    // fork()创建一个进程
if(pid>0)//父进程
{
  for(k=1;k<3;k++)
   { 
     printf("how are you!,k=%d\n",k); 
     sleep(1);
   }
  kill(pid,17);
  wait(0);
  printf("parent exit\n");
  exit(0);
}
else//子进程
{
  signal(17,intfun); //中断
  i=1;
  while(i==1)
   { 
     printf("I am child: j=%d\n",j++); 
     sleep(1);
   }
     printf("child exit\n");
     exit(0);
  }
}

实验结果
此时奇怪的是出现两种结果

第一种
在这里插入图片描述
第二种
在这里插入图片描述

实验4

要求:

  1. 用fork()创建两个子进程,再用signal()让父进程捕捉键盘上发来的中断信号(即按CTRL+C)
  2. 捕捉到中断信号后,父进程调用kill()向两个子进程发出信号,子进程收到信号后分别在显示器上
  3. 输出下列信息并写入本地文件中,然后终止:
    子进程1收到父进程发来的信号,即将终止。
    子进程2收到父进程发来的信号,即将终止。
  4. 父进程等到两个子进程终止后,在显示器上输出如下信息并写入本地文件,然后终止:
    两个子进程已经终止,父进程即将终止。
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>

void waiting();
void stop();
int wait_mark;
int *fp;
void waiting()
{
	while(wait_mark!=0);
}

void stop()
{
	wait_mark=0;
}

void main()
{
char file[20];
int p1,p2;
printf("please input the file name:\n");
scanf("%s",file);
fp = fopen(file,"w+");
signal(SIGINT,SIG_IGN);
while((p1=fork())==-1);
if(p1>0)
{

while((p2=fork())==-1);
if(p2>0)
{
printf("请按CTRL+C终止程序\n");
wait_mark=1;
signal(SIGINT,stop);
waiting();
kill(p1,10);
kill(p2,12);
wait(0);
wait(0);
fprintf(fp,"parent process is killed\n");
exit(0);
}

else
{
	wait_mark=1;
	signal(12,stop);
	waiting();
	lockf(*fp,1,0);//lock
	printf("child 2 prcess is killed by parent\n");
	fprintf(fp,"child 2 prcess is killed by parent\n");
    	lockf(*fp,0,0);//unlock
    	exit(0);
}
}
else
{	
	wait_mark=1;
	signal(10,stop);
	waiting();
	lockf(*fp,1,0);//lock
	printf("child 1 process is killed by parent\n");
	fprintf(fp,"child 1 process is killed by parent\n");
    	lockf(*fp,0,0);//unlock
	exit(0);
}
}

运行结果:

终端屏幕显示:

在这里插入图片描述写入文件内容在这里插入图片描述

signal(SIGINT,SIG_IGN);
SIGINT是中断信号(ctrl + C),它的默认行为是终止该过程。
signal(SIGINT,SIG_IGN)是忽略此信号,也就是此信号不产生我们所需要的动作.
signal(SIGINT,SID_DFL)是系统默认的信号操作.

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值