• Linux Linux程序练习十五(进程间的通信共享内存版)


    /*
     * 题目:
     * 编写程序,要去实现如下功能:
     父进程创建子进程1和子进程2、子进程1向子进程2发送可靠信号,并传送额外数据为子进程1的pid*2;
     子进程2接受可靠信号的值,并发送给父进程,父进程把接受的值进行打印。
     提示:用sigqueue和sigaction实现
     * */
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <errno.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <signal.h>
    #include <sys/shm.h>
    
    /* 分析:
     * 子进程2将pid存入共享内存区,子进程1从共享内存区中读取子进程2的pid,向子进程2发送带数据的信号
     * */
    
    //子进程2信号安装回调函数
    void handler(int sign, siginfo_t * info, void *p)
    {
        if (sign == SIGRTMIN)
        {
            printf("子进程2接收到数据%d
    ",info->si_value.sival_int);
            //向父进程发送信号
            if (sigqueue(getppid(), SIGRTMIN, info->si_value) != 0)
            {
                perror("sigqueue() err");
                return;
            }
            //退出子进程2
            printf("子进程2 quit
    ");
            exit(0);
    
        }
    }
    
    //父进程信号安装回调函数
    void handlerf(int sign, siginfo_t * info, void *p)
    {
        if (sign == SIGRTMIN)
        {
            //打印信号值
            printf("父进程接收的值是%d
    ", info->si_value.sival_int);
        }
    }
    
    int main(int arg, char *args[])
    {
        //创建共享内存区
        int shmid = shmget(IPC_PRIVATE, sizeof(int), 0666);
        if (shmid == -1)
        {
            printf("shmget() failed !
    ");
            return -1;
        }
        pid_t pid = 0;
        pid = fork();
        if (pid == -1)
        {
            perror("fork() err");
            return -1;
        }
        if (pid == 0)
        {
            //子进程1
            printf("子进程1的pid=%d
    ", getpid());
            int *pid2 = NULL;
            //子进程1附加到共享内存区
            pid2 = (int *) shmat(shmid, 0, 0);
            if ((int) pid2 == -1)
            {
                perror("shmat() err");
                return -1;
            }
            //等待进程2向共享内存区写入数据
            while (*pid2 == 0)
            {
                //等待共享内存区中有数据
                sleep(1);
            }
            //向进程2发送可靠信号
            union sigval v1;
            v1.sival_int = getpid() * 2;
            if (sigqueue(*pid2, SIGRTMIN, v1) != 0)
            {
                perror("sigqueue() err");
                return -1;
            }
            //发送完信号后,进程1退出
            printf("子进程1 exit
    ");
            exit(0);
        }
        pid = fork();
        if (pid == -1)
        {
            perror("fork() err");
            return -1;
        }
        if (pid == 0)
        {
            //子进程2
            printf("子进程2的pid=%d
    ", getpid());
            //安装信号SIGRTMIN
            struct sigaction act;
            act.sa_sigaction = handler;
            sigemptyset(&act.sa_mask);
            act.sa_flags = SA_SIGINFO;
            if (sigaction(SIGRTMIN, &act, NULL) != 0)
            {
                printf("sigaction() failed !
    ");
                return -1;
            }
            int *mypid = NULL;
            //子进程2附加到共享内存区
            mypid = (int *) shmat(shmid, 0, 0);
            if ((int) mypid == -1)
            {
                perror("shmat() err");
                return -1;
            }
            //将子进程2的pid放到共享内存区,操作私有共享内存区,映射到系统共享内存区
            *mypid = getpid();
            //等待子进程1向自己发送信号
            while (1)
            {
                printf("子进程2 sleep
    ");
                sleep(1);
            }
        }
        //父进程
        //安装信号SIGRTMIN
        struct sigaction act;
        act.sa_sigaction = handlerf;
        sigemptyset(&act.sa_mask);
        act.sa_flags = SA_SIGINFO;
        if (sigaction(SIGRTMIN, &act, NULL) != 0)
        {
            printf("sigaction() failed !
    ");
            return -1;
        }
        int ret=0;
        //等待子进程
        while(1)
        {
            ret=wait(NULL);
            printf("子进程pid=%d
    ",ret);
            if(ret==-1)
            {
                if(errno==EINTR)
                {
                    continue;
                }
                break;
            }
        }
        //释放共享内存区
        if (shmctl(shmid, IPC_RMID, NULL) != 0)
        {
            printf("shmctl() failed!
    ");
        }
        printf("game is over !
    ");
        return 0;
    }
    
    /*
     * 出错总结:gdb报错:shmat() err: Invalid argument,意思是shmat()参数不正确
     * 经过半天分析,发现我在父进程中没有wait子进程,直接调用了shmctl()函数,把共享内存给释放了,所以报错
     * */

  • 相关阅读:
    python 操作ie 登陆土豆再退出
    python之sqlite3使用详解(转)
    python 获取当前目录下文件(转)
    python中使用time模块计算代码执行效率的精度测试(转)
    pythonhttplib模块使用(转)
    python技巧31[python中使用enum](转)
    python怎样压缩和解压缩ZIP文件(转)
    httplib2python下的http请求终结者(转)
    Python:使用ctypes库调用外部DLL(转)
    整理了下控制ie的代码(转)
  • 原文地址:https://www.cnblogs.com/zhanggaofeng/p/6123957.html
Copyright © 2020-2023  润新知