目录
一、实验目的
1、了解采用信号机制进行进程间通信的原理。
2、掌握通过信号进行进程间通信的方法。
二、实验内容
编写sigaction.c源程序,实现如下功能:
1、a.捕获“Ctrl-C”信号时,输出”I have get SIGINT”
b.捕获“Ctrl-\”信号时, 输出”I have get SIGQUIT”
2、a.设置进程屏蔽字,屏蔽信号SIGINT,接着多次发出信号SIGINT观察结果。通过调用相关函数测试SIGINT是否处于阻塞,如果被屏蔽,输出“The SIGINT signal has been ignored”。
b.取消对SIGINT的屏蔽并挂起进程,将输出”I have get SIGINT.”。观察输出”I have get SIGINT”的次数,并思考解释原因。
三、实验具体分工
组内人员分别独立完成实验
四、实验步骤、源程序及结果截图
编写sigaction.c源程序:
源代码:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
void sigint_handler(int signum) {
printf("I have get SIGINT\n");
}
void sigquit_handler(int signum) {
printf("I have get SIGQUIT\n");
}
int main() {
struct sigaction sa_int, sa_quit;
// 设置SIGINT信号处理函数
sa_int.sa_handler = sigint_handler;
sigemptyset(&sa_int.sa_mask);
sa_int.sa_flags = 0;
sigaction(SIGINT, &sa_int, NULL);
// 设置SIGQUIT信号处理函数
sa_quit.sa_handler = sigquit_handler;
sigemptyset(&sa_quit.sa_mask);
sa_quit.sa_flags = 0;
sigaction(SIGQUIT, &sa_quit, NULL);
// 进入无限循环,等待信号
while (1) {
// 空操作
}
return 0;
}
1、a.捕获“Ctrl-C”信号时,输出”I have get SIGINT”
b.捕获“Ctrl-\”信号时, 输出”I have get SIGQUIT”
运行结果截图:
2、a.设置进程屏蔽字,屏蔽信号SIGINT,接着多次发出信号SIGINT观察结果。通过调用相关函数测试SIGINT是否处于阻塞,如果被屏蔽,输出“The SIGINT signal has been ignored”。
源程序代码:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
void sigint_handler(int signum) {
printf("I have get SIGINT\n");
}
int main() {
struct sigaction sa_int;
// 设置SIGINT信号处理函数
sa_int.sa_handler = sigint_handler;
sigemptyset(&sa_int.sa_mask);
sa_int.sa_flags = 0;
sigaction(SIGINT, &sa_int, NULL);
// 设置进程屏蔽字,屏蔽SIGINT信号
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
sigprocmask(SIG_BLOCK, &mask, NULL);
// 多次发出SIGINT信号
int i;
for (i = 0; i < 5; i++) {
raise(SIGINT);
}
// 检查SIGINT是否被屏蔽
sigset_t pending;
sigpending(&pending);
if (sigismember(&pending, SIGINT)) {
printf("The SIGINT signal has been ignored\n");
}
return 0;
}
运行结果截图:
b.取消对SIGINT的屏蔽并挂起进程,将输出”I have get SIGINT.”。观察输出”I have get SIGINT”的次数,并思考解释原因。
源代码:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
void sigint_handler(int signum) {
printf("I have get SIGINT\n");
}
int main() {
struct sigaction sa_int;
// 设置SIGINT信号处理函数
sa_int.sa_handler = sigint_handler;
sigemptyset(&sa_int.sa_mask);
sa_int.sa_flags = 0;
sigaction(SIGINT, &sa_int, NULL);
// 设置进程屏蔽字,屏蔽SIGINT信号
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
sigprocmask(SIG_BLOCK, &mask, NULL);
// 取消对SIGINT的屏蔽并挂起进程
sigdelset(&mask, SIGINT);
sigsuspend(&mask);
return 0;
}
运行结果:
五、实验问题总结
首先,定义了两个信号处理函数sigint_handler和sigquit_handler,分别用于处理SIGINT和SIGQUIT信号。这些处理函数在收到相应的信号时会被调用,并输出相应的信息。
然后,创建了两个struct sigaction结构体变量sa_int和sa_quit,分别用于设置SIGINT和SIGQUIT信号的处理方式。
对于SIGINT信号,设置sa_int结构体的sa_handler成员为sigint_handler,表示在收到SIGINT信号时调用sigint_handler函数进行处理。sa_int.sa_mask成员被清空,表示在处理SIGINT信号时不屏蔽其他信号。sa_int.sa_flags被设置为0,表示使用默认的标志位。
对于SIGQUIT信号,设置了sa_quit结构体的sa_handler成员为sigquit_handler,表示在收到SIGQUIT信号时调用sigquit_handler函数进行处理。sa_quit.sa_mask成员被清空,表示在处理SIGQUIT信号时不屏蔽其他信号。sa_quit.sa_flags被设置为0,表示使用默认的标志位。
最后,进入一个无限循环,等待信号的到来。当收到SIGINT信号时,会调用sigint_handler函数输出"I have get SIGINT";当收到SIGQUIT信号时,会调用sigquit_handler函数输出"I have get SIGQUIT"。这样,程序会一直等待信号的到来,并根据不同的信号执行相应的处理函数。
对于屏蔽测试,使用sigpending函数获取当前未决的信号集合,并将结果存储在pending变量中。使用sigismember函数检查SIGINT信号是否在未决信号集合中,如果是,则输出"The SIGINT signal has been ignored",表示SIGINT信号被屏蔽了。
对于解除屏蔽,使用sigprocmask函数设置进程的屏蔽字,将SIGINT信号加入屏蔽字,这样进程在接收到SIGINT信号时不会立即响应。之后使用sigdelset函数取消对SIGINT的屏蔽,并使用sigsuspend函数挂起进程,等待接收到信号。