用程序验证信号集相同信号共存,信号继承,嵌套的特点以及客户端和服务器通讯程序解析

一.验证信号集的特点。

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给父进程。
            }
        }
    }
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肖爱Kun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值