一.验证信号集的特点。
1.是否有相同的信号
#include <stdio.h>
#include <signal.h>
int main(int argc,char *argv[])
{
//1. 定义信号集
sigset_t set;
//2. 将所有的信号都添加到信号集中
sigfillset(&set);
//3. 判断一下在不在集合中
int ret;
ret = sigismember(&set,SIGINT);
if(ret == 1)
printf("is member!\n"); //√
else
printf("is not member\n");
//4. 清空信号集
sigemptyset(&set);
//5. 判断一下在不在集合中
ret = sigismember(&set,SIGINT);
if(ret == 1)
printf("is member!\n");
else
printf("is not member\n");//√
//6. 单独将SIGINT信号添加到信号集中
sigaddset(&set,SIGINT);
//7. 判断一下在不在集合中
ret = sigismember(&set,SIGINT);//√
if(ret == 1)
printf("is member!\n");
else
printf("is not member\n");
//8. 将SIGINT删除
sigdelset(&set,SIGINT);
//9. 判断一下在不在集合中
ret = sigismember(&set,SIGINT);
if(ret == 1)
printf("is member!\n");
else
printf("is not member\n");//√
return 0;
}
--------------------------------------------------------------------------------------------------------------------------------
2.阻塞属性会不会被继承
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
void my_func(int sig)
{
printf("helloworld!\n");
}
int main(int argc,char *argv[])
{
//1. 让父进程先捕捉这个信号
signal(SIGUSR1,my_func);
//思路: 让父进程先有阻塞属性,然后让父进程带着阻塞状态去产生一个子进程
//2. 定义一个信号集
sigset_t set;
//3. 清空信号集
sigemptyset(&set);
//4. 将SIGUSR1添加到信号集中
sigaddset(&set,SIGUSR1);
//5. 给信号集设置阻塞状态
sigprocmask(SIG_BLOCK,&set,NULL);
//6. 带着这个信号集去产生一个子进程。
pid_t x;
x = fork();
int i;
if(x > 0)
{
printf("parent pid = %d\n",getpid());
for(i=20;i>0;i--)
{
sleep(1);
printf("parent i = %d\n",i); //在这20s内,给父进程发送一个SIGUSR1信号。
}
sigprocmask(SIG_UNBLOCK,&set,NULL);
printf("parent unblock!\n");
wait(NULL);
exit(0);
}
if(x == 0)
{
printf("child pid = %d\n",getpid());
for(i=40;i>0;i--)
{
sleep(1);
printf("child i = %d\n",i); //在这20s~40s内,给子进程发送一个SIGUSR1信号。
}
sigprocmask(SIG_UNBLOCK,&set,NULL);
printf("child unblock!\n");
exit(0);
}
}
--------------------------------------------------------------------------------------------------------------------------------
3.挂起队列的信号会不会被继承
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
void func(int sig)
{
printf("helloworld!\n");
}
int main(int argc,char *argv[])
{
//0. 捕捉信号
signal(SIGUSR1,func);
//1. 定义一个信号集
sigset_t set;
//2. 清空信号集
sigemptyset(&set);
//3. 将SIGUSR1添加到信号集中
sigaddset(&set,SIGUSR1);
//4. 设置信号集为阻塞状态
sigprocmask(SIG_BLOCK,&set,NULL);
//5. 持续一段,这段期间内,我们要发送一个SIGUSR1信号给父进程
int i;
for(i=20;i>0;i--)
{
sleep(1);
printf("parent i = %d\n",i); //在此20s内,一定要发送SIGUSR1信号给父进程
}
//6. 这时候,父进程的挂起队列就有SIGUSR1。
//7. 带着挂起队列去产生一个子进程
pid_t x;
x = fork();
if(x > 0)
{
for(i=10;i>0;i--)
{
sleep(1);
printf("parent unblock : %d\n",i);
}
sigprocmask(SIG_UNBLOCK,&set,0);
wait(NULL);
exit(0);
}
if(x == 0)
{
for(i=20;i>0;i--)
{
sleep(1);
printf("child unblock : %d\n",i);
}
sigprocmask(SIG_UNBLOCK,&set,0);
exit(0);
}
return 0;
}
--------------------------------------------------------------------------------------------------------------------------------
4.进程在相应信号时,能否相互嵌套
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
void func1(int sig)
{
char str[] = "helloworld";
int i;
for(i=0;str[i]!='\0';i++)
{
fprintf(stderr,"%c",str[i]);
sleep(1);
}
}
void func2()
{
char str[] = "appletree";
int i;
for(i=0;str[i]!='\0';i++)
{
fprintf(stderr,"%c",str[i]);
sleep(1);
}
}
int main()
{
printf("parent pid = %d\n",getpid());
signal(SIGUSR1,func1);
signal(SIGUSR2,func2);
while(1)
pause();
}
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
二.实现客户端和服务器收发通讯。
//服务器程序设计
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <strings.h>
#define S2C 10 //服务器发送给客户端消息类型
#define C2S 20 //客户端发送给服务器消息类型
//定义写入数据结构体
struct msgbuf{
long mtype; //消息的类型
char mtext[50];//消息正文
};
void func(int sig)
{
exit(0);
}
int main(int argc,char *argv[])
{
//1. 为消息队列申请key值与ID号
key_t key = ftok(".",10);
int msgid = msgget(key,IPC_CREAT|0666);
//2. 带着这条队列去产生一个小孩
pid_t x;
x = fork();
if(x > 0) //父进程 发送消息
{
signal(SIGCHLD,func);
//定义写入数据结构体变量gec
struct msgbuf gec;
int ret;
while(1)
{
//清空写入数据结构体变量
bzero(&gec,sizeof(gec));
//定义写入数据结构体的消息类型
gec.mtype = S2C;//服务器发送给客户端
//从标准输入获取数据存入写入数据结构体的消息正文缓冲区gec.mtext中
/* gec.mtext 字符数组 等价于 数组首元素的地址
sizeof(gec.mtext) 读取的字节大小
stdin 标准输入缓冲区文件指针
*/
fgets(gec.mtext,sizeof(gec.mtext),stdin);
//msgsnd函数写入数据到消息队列中
ret = msgsnd(msgid,&gec,strlen(gec.mtext),0);
if(ret == -1)
{
printf("msgsnd error!\n");
}
if(strncmp(gec.mtext,"quit",4) == 0)
{
//发送信号给子进程,当子进程收到SIGUSR1信号类型的时候,执行函数func()
kill(x,SIGUSR1);
exit(0);
}
}
}
if(x == 0) //子进程 接收消息
{
//捕捉父进程发送的SIGUSR1信号
signal(SIGUSR1,func);
//定义写入数据结构体变量
struct msgbuf gec;
int ret;
while(1)
{
//清空写入数据结构体变量
bzero(&gec,sizeof(gec));
//读取消息队列写入数据结构中的数据
ret = msgrcv(msgid,&gec,sizeof(gec.mtext),C2S,0);
if(ret == -1)
{
//读取失败
printf("msgrcv error!\n");
}
printf("from client:%s",gec.mtext);
if(strncmp(gec.mtext,"quit",4) == 0)
{
msgctl(msgid,IPC_RMID,NULL); //删除消息队列
exit(0); //子进程推出的时候,系统会自动发送SIGCHLD给父进程。
}
}
}
}
//客户端程序设计
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <strings.h>
#define S2C 10
#define C2S 20
//定义写入数据结构体
struct msgbuf{
long mtype; //消息类型
char mtext[50];//正文
};
void func(int sig)
{
exit(0);
}
int main(int argc,char *argv[])
{
//1. 为消息队列申请key值与ID号
key_t key = ftok(".",10);
int msgid = msgget(key,IPC_CREAT|0666);
//2. 带着这条队列去产生一个小孩
pid_t x;
x = fork();
if(x > 0) //父进程 发送消息
{
//捕捉子进程退出时的信号SIGCHLD
signal(SIGCHLD,func);
//定义写入数据结构体变量
struct msgbuf gec;
int ret;
while(1)
{
//清空写入数据结构体
bzero(&gec,sizeof(gec));
//定义写入数据结构体消息的类型
gec.mtype = C2S;
//从标准输入缓冲区中获取数据写入写入数据结构体的消息正文
fgets(gec.mtext,sizeof(gec.mtext),stdin);
//写入数据到消息队列中
ret = msgsnd(msgid,&gec,strlen(gec.mtext),0);
if(ret == -1)
{
printf("msgsnd error!\n");
}
if(strncmp(gec.mtext,"quit",4) == 0)
{
kill(x,SIGUSR1);
exit(0);
}
}
}
if(x == 0) //子进程 接收消息
{
//捕捉父进程发送的SIGUSR1信号,执行函数func()
signal(SIGUSR1,func);
//定义写入数据结构体变量
struct msgbuf gec;
int ret;
while(1)
{
//清空写入数据结构体
bzero(&gec,sizeof(gec));
读取消息队列中的数据
ret = msgrcv(msgid,&gec,sizeof(gec.mtext),S2C,0);
if(ret == -1)
{
printf("msgrcv error!\n");
}
printf("from server:%s",gec.mtext);
if(strncmp(gec.mtext,"quit",4) == 0)
{
msgctl(msgid,IPC_RMID,NULL); //删除消息队列
exit(0); //子进程 会自动发送SIGCHLD给父进程。
}
}
}
}