实验题目:信号通信
实验前置知识:
信号处理函数:
(1)信号安装函数
signal()函数示例:
#include"signal.h"/使用两个函数都必须包含这个头文件
#include"unistd.h"
#include"stdio.h"
//信号处理函数,调用时参数dunno会得到信号的值
void sigroutine(int dunno){
switch(dunno){
case 1:printf("Git a signal-SIGHUP\n");break;
case 2:printf("Git a signal-SIGINT\n");break;
case 3:printf("Git a signal-SIGQUIT\n");break;
}
return;
}
int main(){
printf("process id is %d\n",getpid());
//下面设置了3个信号处理函数
signal(SIGHUP,sigroutine); //通过kill操作得到Git a signal-SIGHUP
signal(SIGINT,sigroutine); //通过Ctrl+C得到Git a signal-SIGINT
signal(SIGQUIT,sigroutine); //通过Ctrl+\得到Git a signal-SIGQUIT
for(;;);
}
//kill -9 31658 可以终止进程
操作结果:
sigaction()函数示例:
#include"signal.h"//使用两个函数都必须包含这个头文件
#define PROMPT"你想终止程序吗"
char *prompt=PROMPT;
void ctrl_c_op(int signo){
write(STDERR_FILENO,prompt,strlen(prompt));
}
/*
int sigaction(int signum,const struct sigaction *act.struct sigaction *oact);
struct sigaction{
void (*sa_handler)(int signum);
void (*sa_sigaction)(int siginfo_t *info,void *act)
sigset_t sa_mask;
int sa_flags;
void(*sa_restore)(void);
}
*/
int main(){
struct sigaction act;
act.sa_handler=ctrl_c_op;
sig.sa_flags=0;
if(sigaction(SIGINT,&act,NULL)<0){
fprintf(stderr,"Signal Action Error:%s\n\a",strerror(errno));
return 0;
}
while(1);
}
(2)信号发送函数
必须包含的头文件
#include<sys/types.h>
#include<signal.h>
kill()函数:
int kill(pid_t pid,int sig);
若pid>0,信号sig发送给进程号为pid的进程
若pid=0,信号sig发送给当前进程所属的进程组里的所有进程
若pid=-1,信号sig发送给除了号进程和自身以外的所有进程
若pid<-1,信号sig发送给属于进程组 -pid 的所有进程
若sig=0,将不发送信号
返回值为0时,函数执行成功
返回值为-1时,错误 错误代码error
error=EINVAL,信号sig无效
error=SRCH,pid指定的进程不存在
error=EPERM,权限不足
raise()函数:
用于向自身发送信号
int raise(sint sig);
raise(signo)=kill(getpid(),signo)
alarm()函数:
用于设置一个定时器,时间到则发送SIGALRM信号给进程
unsigned int alarm(unsigned int seconds);
setitimer()函数:
定时器
pause()函数:
是当前进程暂停进入睡眠状态,直到被信号所中断
int pausee(void)
(3)信号操作函数
int sigemptyset(sigset_t *set);
初始化信号量集合set,将set设置为空
int sigfillset(sigset_t *set);
初始化信号量集合,将信号量集合设置为所有信号的集合
int sigfaddset(sigset_t *set,int signo);
将信号signo加入到信号集合之中
int sigdelset(sigset_t *set,int signo);
将信号从信号集合中删除
int sigmember(sigset_t *set,int signo);
查询信号是否在信号集合中
最关键信号
int sigprocmask(int how,const sigset_t *set,sigset_t *oset);
先设置号信号集合set,将指定的信号集合set加入到进程的信号阻塞集合中去
附上实验报告
实验题目:信号通信
实验目的:本实验的目的主要是使学生理解信号概念、掌握信号通信机制及借此实现Linux进程间通信的原理。
实验要求:利用信号通信机制在父子进程及兄弟进程间进行通信。
实验内容:
1.编写程序,实现阻塞型通信。
源程序:
#include"unistd.h"
#include"sys/types.h"
#include"signal.h"
#include"wait.h"
void sigchild_handler(int sig)
{
pid_t pid;
int status;
for(;(pid=waitpid(-1,&status,WNOHANG))>0;)
{
printf("child:%ddied:%d\n",pid,WEXITSTATUS(status));
printf("hi,parent process received SIGHLD signal successfully!\n");
}
return;
}
int main()
{
int pc;
pc=fork();
if(pc==0)
{
printf("child process pid%d!\n",getpid());
sleep(3);
return 0;
}
}
执行流程:
[2016236153@localhost ~]$ vi barrage.c
[2016236153@localhost ~]$ gcc -o barrage barrage.c
[2016236153@localhost ~]$ ./barrage
child process pid19408!
child:19408died:0
hi,parent process received SIGHLD signal successfully!
[2016236153@localhost ~]$
运行结果:
2.编写程序,实现非阻塞型通信
源程序:
#include"signal.h"
#include"stdlib.h"
void sigint_handler(int sig){
printf("received SIGINT signal successed!\n");
return;
}
void main(){
int pc;
pc=fork();
if(pc==0){
printf("this is child process pid %d\n",getpid());
sleep(3);
printf("this is child process pid first sleep %d\n",getpid());
sleep(3);
printf("this is child process pid second sleep %d\n",getpid());
return;
}else if(pc>0){
signal(SIGINT,sigint_handler);
pause();
}else if(pc<0){
printf("Error!\n");
return;
}
}
执行流程:
[2016236153@localhost ~]$ vi unbarrage.c
[2016236153@localhost ~]$ gcc -o unbarrage unbarrage.c
[2016236153@localhost ~]$ ./
aa* barrage1* dsl/ memos/ unbarrage*
b* barrage2* hello* q*
barrage* dengshenglin/ lab8* sigmaltest*
[2016236153@localhost ~]$ ./unbarrage
this is child process pid 19108
this is child process pid first sleep 19108
this is child process pid second sleep 19108
^Creceived SIGINT signal successed!
[2016236153@localhost ~]$ bg
bg: No current job.
运行结果: