IO进程线程 day7 进程间通信

发布时间:2024年01月09日

?1.使用消息队列完成两个进程之间相互通信

?2.信号通信相关代码的重新实现

(1)signal函数的实例

#include <head.h>

//定义信号处理函数
void handler(int signum)
{
    if(signum == SIGINT)      //表明要处理2号信号
    {
        printf("用户按下了ctrl + c键\n");
    }

    if(signum == SIGTSTP)          //处理暂停信号
    {

        printf("用户按下了ctrl + z键\n");
    }
}

/****************************主程序********************/
int main(int argc, const char *argv[])
{

    /*将SIGINT信号忽略
    if(signal(SIGINT, SIG_IGN) == SIG_ERR)
    {
        perror("signal error");
        return -1;
    }
    */

    /*将SIGINT信号默认处理
    if(signal(SIGINT, SIG_DFL) == SIG_ERR)
    {
        perror("signal error");
        return -1;
    }
    */

    //将SIGINT信号捕获
    if(signal(SIGINT, handler) == SIG_ERR)
    {
        perror("signal error");
        return -1;
    }

    //绑定SIGTSTP信号 ctrl + z
    if(signal(SIGTSTP, handler) == SIG_ERR)
    {
        perror("signal error");
        return -1;
    }



    while(1)
    {
        sleep(1);
        printf("我真的还想再活五百年\n");
    }

    return 0;
}

(2)尝试捕获SIGSTOP信号

#include <head.h>

//定义信号处理函数
void handler(int signum)
{
    if(signum == SIGINT)      //表明要处理2号信号
    {
        printf("用户按下了ctrl + c键\n");
    }

    if(signum == SIGTSTP)          //处理暂停信号
    {

        printf("用户按下了ctrl + z键\n");
    }


    if(signum == SIGSTOP)          //处理暂停信号
    {

        printf("用户按下了ctrl + z键\n");
    }
}

/****************************主程序********************/
int main(int argc, const char *argv[])
{
    /*尝试忽略SIGSTOP信号
    if(signal(SIGSTOP, SIG_IGN) == SIG_ERR)
    {
        perror("signal error");
        return -1;
    }
    */

    /*尝试捕获SIGSTOP信号
    if(signal(SIGSTOP, handler) == SIG_ERR)
    {
        perror("signal error");
        return -1;
    }
    */

    //尝试默认处理SIGSTOP信号
    if(signal(SIGSTOP, SIG_DFL) == SIG_ERR)
    {
        perror("signal error");
        return -1;
    }

    while(1)
    {
        sleep(1);
        printf("我真的还想再活五百年\n");
    }

    return 0;
}

(3)使用信号的方式以非阻塞的形式回收僵尸进程(SIGCHLD)

#include <head.h>

//定义信号处理函数
void handler(int signum)
{
    if(signum == SIGCHLD)
    {
        //以非阻塞的形式回收僵尸进程,直到所有的僵尸进程全部回收结束
        while(waitpid(-1, NULL, WNOHANG) >0 );
    }
}


int main(int argc, const char *argv[])
{


    //捕获子进程发来的SIGCHLD信号
    if(signal(SIGCHLD, handler) == SIG_ERR)
    {
        perror("signal error");
        return -1;
    }

    for(int i=0; i<10; i++)
    {
        if(fork() == 0)
        {
            exit(EXIT_SUCCESS);
        }
    }


    while(1);


    return 0;
}

(4)使用闹钟信号完成一个定时器(SIGALRM),该信号由alarm函数设置的时间超时后产生

#include <head.h>

int main(int argc, const char *argv[])
{
    printf("%d\n", alarm(10));           //0

    sleep(5);


    printf("%d\n", alarm(10));           //5

    while(1);

    return 0;
}

(5)使用SIGALRM信号模拟斗地主出牌场景

#include <head.h>

//定义信号处理函数
void handler(int signo)
{
    if(signo == SIGALRM)
    {
        printf("系统已经随机为您出一张牌\n");
        alarm(5);
    }
}



int main(int argc, const char *argv[])
{
    
    char ch;

    //将SIGALRM信号绑定到信号处理函数中
    if(signal(SIGALRM, handler) == SIG_ERR)
    {
        perror("signal error");
        return -1;
    }

    while(1)
    {
        alarm(5);
        
        printf("请出牌:");
        scanf("%c", &ch);
        getchar();

        printf("您出的牌为:%c\n", ch);
    }

    return 0;
}

(6)信号发送函数(kill、raise)

#include <head.h>

//定义信号处理函数
void handler(int signo)
{
    if(signo == SIGUSR1)
    {
        printf("逆子何至于此\n");

        raise(SIGKILL);     //自杀
    }
}


int main(int argc, const char *argv[])
{
    
    //定义进程号
    pid_t pid = fork();

    if(pid > 0)
    {
        //父进程

        //将SIGUSR1信号绑定
        if(signal(SIGUSR1, handler) == SIG_ERR)
        {
            perror("signal error");
            return -1;
        }
        
        while(1)
        {
            printf("我真的还想再活五百年\n");
            sleep(1);
        }

    }else if(pid == 0)
    {
        //子进程
        printf("人生得意须尽欢,莫使金樽空对月\n");

        sleep(3);

        printf("我看透了红尘, 父亲跟我一起走吧\n");

        //向父进程发送一个信号
        kill(getppid(), SIGUSR1);

        exit(EXIT_SUCCESS);        //退出进程


    }else
    {
        perror("fork error");
        return -1;
    }


    return 0;
}

3.共享内存相关代码重新实现

(1)发送端

#include <head.h>
#define PAGE_SIZE 4096

int main(int argc, const char *argv[])
{
    //1、创建key值
    key_t key = -1;
    if((key = ftok("/", 't')) == -1)
    {
        perror("ftok error");
        return -1;
    }
    printf("key = %#x\n", key);

    //2、将物理内存创建出共享内存段
    int shmid = 0;
    if((shmid = shmget(key, PAGE_SIZE, IPC_CREAT|0664)) == -1)
    {
        perror("shmget error");
        return -1;
    }
    printf("shmid = %d\n", shmid);

    //3、将共享内存段地址映射到用户空间
    //NULL表示让系统自动选择页的分段
    //0表示当前进程对共享内存具有读写功能
    char *addr = (char *)shmat(shmid, NULL, 0);
    if(addr == (void *)-1)
    {
        perror("shmat error");
        return -1;
    }
    printf("addr = %p\n", addr);
    
    //4、操作共享内存
    //char buf[128] = "";
    while(1)
    {
        fgets(addr, PAGE_SIZE, stdin);   //从终端输入数据
        addr[strlen(addr) - 1] = '\0';    //将换行换成'\0'

        if(strcmp(addr, "quit") == 0)
        {
            break;
        }
    }

    
    //5、取消映射

    while(1);

    return 0;
}

(2)接收端

#include <head.h>
#define PAGE_SIZE 4096

int main(int argc, const char *argv[])
{
    //1、创建key值
    key_t key = -1;
    if((key = ftok("/", 't')) == -1)
    {
        perror("ftok error");
        return -1;
    }
    printf("key = %#x\n", key);

    //2、将物理内存创建出共享内存段
    int shmid = 0;
    if((shmid = shmget(key, PAGE_SIZE, IPC_CREAT|0664)) == -1)
    {
        perror("shmget error");
        return -1;
    }
    printf("shmid = %d\n", shmid);

    //3、将共享内存段地址映射到用户空间
    //NULL表示让系统自动选择页的分段
    //0表示当前进程对共享内存具有读写功能
    char *addr = (char *)shmat(shmid, NULL, 0);
    if(addr == (void *)-1)
    {
        perror("shmat error");
        return -1;
    }
    printf("addr = %p\n", addr);
    
    //4、操作共享内存
    //char buf[128] = "";
    while(1)
    {
    
        printf("共享内存中的数据为:%s\n", addr);
        sleep(1);

        if(strcmp(addr, "quit") == 0)
        {
            break;
        }
    }

    
    //5、取消映射
    if(shmdt(addr) == -1)
    {
        perror("shmdt error");
        return -1;
    }


    //6、删除共享内存
    if(shmctl(shmid, IPC_RMID, NULL) == -1)
    {
        perror("shmctl error");
        return -1;
    }

    return 0;
}

文章来源:https://blog.csdn.net/2203_75782206/article/details/135489649
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。